From: daiwei Date: Fri, 20 Jun 2025 06:26:52 +0000 (+0800) Subject: chore: Merge branch 'vapor' into edison/fix/vaporOnce X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d8183e85bf1f777a2502176224dca11dadcc7928;p=thirdparty%2Fvuejs%2Fcore.git chore: Merge branch 'vapor' into edison/fix/vaporOnce --- d8183e85bf1f777a2502176224dca11dadcc7928 diff --cc packages/runtime-vapor/__tests__/apiCreateDynamicComponent.spec.ts index 448bd2c315,e912af2851..89514e1770 --- a/packages/runtime-vapor/__tests__/apiCreateDynamicComponent.spec.ts +++ b/packages/runtime-vapor/__tests__/apiCreateDynamicComponent.spec.ts @@@ -55,41 -63,51 +63,89 @@@ describe('api: createDynamicComponent' expect(html()).toBe('') }) + test('with v-once', async () => { + const val = shallowRef(A) + + const { html } = define({ + setup() { + return createDynamicComponent(() => val.value, null, null, true, true) + }, + }).render() + + expect(html()).toBe('AAA') + + val.value = B + await nextTick() + expect(html()).toBe('AAA') // still AAA + }) + + test('fallback with v-once', async () => { + const val = shallowRef('button') + const id = ref(0) + const { html } = define({ + setup() { + return createDynamicComponent( + () => val.value, + { id: () => id.value }, + null, + true, + true, + ) + }, + }).render() + + expect(html()).toBe('') + + id.value++ + await nextTick() + expect(html()).toBe('') + }) ++ + test('render fallback with insertionState', async () => { + const { html, mount } = define({ + setup() { + const html = ref('hi') + const n1 = template('
', true)() as any + setInsertionState(n1) + const n0 = createComponentWithFallback( + resolveDynamicComponent('button') as any, + ) as any + renderEffect(() => setHtml(n0, html.value)) + return n1 + }, + }).create() + + mount() + expect(html()).toBe('
') + }) + + test('switch dynamic component children', async () => { + const CompA = defineVaporComponent({ + setup() { + return template('
A
')() + }, + }) + const CompB = defineVaporComponent({ + setup() { + return template('
B
')() + }, + }) + + const current = shallowRef(CompA) + const { html } = define({ + setup() { + const t1 = template('
') + const n2 = t1() as any + setInsertionState(n2) + createDynamicComponent(() => current.value) + return n2 + }, + }).render() + + expect(html()).toBe('
A
') + + current.value = CompB + await nextTick() + expect(html()).toBe('
B
') + }) }) diff --cc packages/runtime-vapor/__tests__/component.spec.ts index 871df18077,22294b1e73..b8a0180762 --- a/packages/runtime-vapor/__tests__/component.spec.ts +++ b/packages/runtime-vapor/__tests__/component.spec.ts @@@ -13,8 -13,8 +14,9 @@@ import createComponent, createIf, createTextNode, + defineVaporComponent, renderEffect, + setInsertionState, template, } from '../src' import { makeRender } from './_utils' diff --cc packages/runtime-vapor/src/apiCreateDynamicComponent.ts index a1b1e3e98f,945e0f38d8..9e51e81d97 --- a/packages/runtime-vapor/src/apiCreateDynamicComponent.ts +++ b/packages/runtime-vapor/src/apiCreateDynamicComponent.ts @@@ -10,8 -16,15 +16,16 @@@ export function createDynamicComponent rawProps?: RawProps | null, rawSlots?: RawSlots | null, isSingleRoot?: boolean, + once?: boolean, ): VaporFragment { + const _insertionParent = insertionParent + const _insertionAnchor = insertionAnchor + if (isHydrating) { + locateHydrationNode() + } else { + resetInsertionState() + } + const frag = __DEV__ ? new DynamicFragment('dynamic-component') : new DynamicFragment() @@@ -29,10 -41,11 +43,14 @@@ ), value, ) - }) + } + + if (once) renderFn() + else renderEffect(renderFn) + if (!isHydrating && _insertionParent) { + insert(frag, _insertionParent, _insertionAnchor) + } + return frag } diff --cc packages/runtime-vapor/src/component.ts index 27f14f7122,af15133dbe..da65f24d55 --- a/packages/runtime-vapor/src/component.ts +++ b/packages/runtime-vapor/src/component.ts @@@ -468,12 -473,19 +476,20 @@@ export function createComponentWithFall rawProps?: LooseRawProps | null, rawSlots?: LooseRawSlots | null, isSingleRoot?: boolean, + once?: boolean, ): HTMLElement | VaporComponentInstance { if (!isString(comp)) { - return createComponent(comp, rawProps, rawSlots, isSingleRoot) + return createComponent(comp, rawProps, rawSlots, isSingleRoot, once) } + const _insertionParent = insertionParent + const _insertionAnchor = insertionAnchor + if (isHydrating) { + locateHydrationNode() + } else { + resetInsertionState() + } + const el = document.createElement(comp) // mark single root ;(el as any).$root = isSingleRoot diff --cc packages/runtime-vapor/src/componentProps.ts index dbc1386e39,9cf65c5714..6d1c686c94 --- a/packages/runtime-vapor/src/componentProps.ts +++ b/packages/runtime-vapor/src/componentProps.ts @@@ -21,9 -21,9 +21,10 @@@ import validateProps, warn, } from '@vue/runtime-dom' + import { ReactiveFlags } from '@vue/reactivity' import { normalizeEmitsOptions } from './componentEmits' import { renderEffect } from './renderEffect' +import { pauseTracking, resetTracking } from '@vue/reactivity' export type RawProps = Record unknown> & { // generated by compiler for :[key]="x" or v-bind="x"