diff options
| author | 2024-09-17 14:54:49 +0200 | |
|---|---|---|
| committer | 2024-09-17 14:54:49 +0200 | |
| commit | b75bfc8cc41f5c631c10055b78670fdc26dff23a (patch) | |
| tree | 965101f6d8231cf1aaae82cf1bf526d360c5e91a /packages/integrations/vue/client.js | |
| parent | a2f8c5d85ff15803f5cedf9148cd70ffc138ddef (diff) | |
| download | astro-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/client.js')
| -rw-r--r-- | packages/integrations/vue/client.js | 46 | 
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 });  	}; | 
