From 653856627ce4636d841e744b7488cac6f44e4eb6 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 2 Jan 2024 21:04:58 +0000 Subject: [PATCH] fix(nuxt): reuse intermediate setup state in `` (#25009) Co-authored-by: julien huang --- .../nuxt/src/app/components/client-only.ts | 39 ++++++++++--------- .../basic/components/ClientWrapped.client.vue | 4 +- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/packages/nuxt/src/app/components/client-only.ts b/packages/nuxt/src/app/components/client-only.ts index c1ce985ea5..a24c0864b9 100644 --- a/packages/nuxt/src/app/components/client-only.ts +++ b/packages/nuxt/src/app/components/client-only.ts @@ -1,4 +1,4 @@ -import { createElementBlock, createElementVNode, createStaticVNode, defineComponent, getCurrentInstance, h, onMounted, ref } from 'vue' +import { cloneVNode, createElementBlock, createStaticVNode, defineComponent, getCurrentInstance, h, onMounted, ref } from 'vue' import type { ComponentInternalInstance, ComponentOptions } from 'vue' import { getFragmentHTML } from './utils' @@ -33,11 +33,11 @@ export function createClientOnly (component: T) { if (clone.render) { // override the component render (non script setup component) - clone.render = (ctx: any, ...args: any[]) => { - if (ctx.mounted$) { - const res = component.render?.bind(ctx)(ctx, ...args) + clone.render = (ctx: any, cache: any, $props: any, $setup: any, $data: any, $options: any) => { + if ($setup.mounted$ ?? ctx.mounted$) { + const res = component.render?.bind(ctx)(ctx, cache, $props, $setup, $data, $options) return (res.children === null || typeof res.children === 'string') - ? createElementVNode(res.type, res.props, res.children, res.patchFlag, res.dynamicProps, res.shapeFlag) + ? cloneVNode(res) : h(res) } else { const fragment = getFragmentHTML(ctx._.vnode.el ?? null) ?? ['
'] @@ -70,19 +70,22 @@ export function createClientOnly (component: T) { return Promise.resolve(component.setup?.(props, ctx) || {}) .then((setupState) => { - return typeof setupState !== 'function' - ? { ...setupState, mounted$ } - : (...args: any[]) => { - if (mounted$.value) { - const res = setupState(...args) - return (res.children === null || typeof res.children === 'string') - ? createElementVNode(res.type, res.props, res.children, res.patchFlag, res.dynamicProps, res.shapeFlag) - : h(res) - } else { - const fragment = getFragmentHTML(instance?.vnode.el ?? null) ?? ['
'] - return import.meta.client ? createStaticVNode(fragment.join(''), fragment.length) : h('div', ctx.attrs) - } - } + if (typeof setupState !== 'function') { + setupState = setupState || {} + setupState.mounted$ = mounted$ + return setupState + } + return (...args: any[]) => { + if (mounted$.value) { + const res = setupState(...args) + return (res.children === null || typeof res.children === 'string') + ? cloneVNode(res) + : h(res) + } else { + const fragment = getFragmentHTML(instance?.vnode.el ?? null) ?? ['
'] + return import.meta.client ? createStaticVNode(fragment.join(''), fragment.length) : h('div', ctx.attrs) + } + } }) } diff --git a/test/fixtures/basic/components/ClientWrapped.client.vue b/test/fixtures/basic/components/ClientWrapped.client.vue index 586a6d71bf..dc2efb5cfe 100644 --- a/test/fixtures/basic/components/ClientWrapped.client.vue +++ b/test/fixtures/basic/components/ClientWrapped.client.vue @@ -4,11 +4,11 @@ function exposedFunc () { } defineExpose({ exposedFunc }) - +const $hello = ref('hello') await new Promise(resolve => setTimeout(resolve, 300)) onMounted(() => { - console.log('mounted') + console.log('mounted', $hello.value) })