summaryrefslogtreecommitdiff
path: root/packages/integrations/vue
diff options
context:
space:
mode:
authorGravatar Johannes Spohr <johannes.spohr@carvia.de> 2024-09-17 14:54:49 +0200
committerGravatar GitHub <noreply@github.com> 2024-09-17 14:54:49 +0200
commitb75bfc8cc41f5c631c10055b78670fdc26dff23a (patch)
tree965101f6d8231cf1aaae82cf1bf526d360c5e91a /packages/integrations/vue
parenta2f8c5d85ff15803f5cedf9148cd70ffc138ddef (diff)
downloadastro-b75bfc8cc41f5c631c10055b78670fdc26dff23a.tar.gz
astro-b75bfc8cc41f5c631c10055b78670fdc26dff23a.tar.zst
astro-b75bfc8cc41f5c631c10055b78670fdc26dff23a.zip
Fix vue resetting state when using view transition persistence (#11946)
* Fix vue resetting state when using view transition persistence * Avoid calling internal apis when forcing vue component update
Diffstat (limited to 'packages/integrations/vue')
-rw-r--r--packages/integrations/vue/client.js46
1 files changed, 32 insertions, 14 deletions
diff --git a/packages/integrations/vue/client.js b/packages/integrations/vue/client.js
index 807f843fc..58ee11d5c 100644
--- a/packages/integrations/vue/client.js
+++ b/packages/integrations/vue/client.js
@@ -2,6 +2,9 @@ import { setup } from 'virtual:@astrojs/vue/app';
import { Suspense, createApp, createSSRApp, h } from 'vue';
import StaticHtml from './static-html.js';
+// keep track of already initialized apps, so we don't hydrate again for view transitions
+let appMap = new WeakMap();
+
export default (element) =>
async (Component, props, slotted, { client }) => {
if (!element.hasAttribute('ssr')) return;
@@ -15,21 +18,36 @@ export default (element) =>
const isHydrate = client !== 'only';
const bootstrap = isHydrate ? createSSRApp : createApp;
- const app = bootstrap({
- name,
- render() {
- let content = h(Component, props, slots);
- // related to https://github.com/withastro/astro/issues/6549
- // if the component is async, wrap it in a Suspense component
- if (isAsync(Component.setup)) {
- content = h(Suspense, null, content);
- }
- return content;
- },
- });
- await setup(app);
- app.mount(element, isHydrate);
+ // keep a reference to the app, props and slots so we can update a running instance later
+ let appInstance = appMap.get(element);
+
+ if (!appInstance) {
+ appInstance = {
+ props,
+ slots,
+ };
+ const app = bootstrap({
+ name,
+ render() {
+ let content = h(Component, appInstance.props, appInstance.slots);
+ appInstance.component = this;
+ // related to https://github.com/withastro/astro/issues/6549
+ // if the component is async, wrap it in a Suspense component
+ if (isAsync(Component.setup)) {
+ content = h(Suspense, null, content);
+ }
+ return content;
+ },
+ });
+ await setup(app);
+ app.mount(element, isHydrate);
+ appMap.set(element, appInstance);
+ } else {
+ appInstance.props = props;
+ appInstance.slots = slots;
+ appInstance.component.$forceUpdate();
+ }
element.addEventListener('astro:unmount', () => app.unmount(), { once: true });
};