]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(runtime-vapor): add v-once support to createDynamicComponent
authordaiwei <daiwei521@126.com>
Tue, 10 Jun 2025 08:30:51 +0000 (16:30 +0800)
committerdaiwei <daiwei521@126.com>
Tue, 10 Jun 2025 08:30:51 +0000 (16:30 +0800)
packages/runtime-vapor/__tests__/apiCreateDynamicComponent.spec.ts
packages/runtime-vapor/src/apiCreateDynamicComponent.ts
packages/runtime-vapor/src/component.ts

index 2f6cd7b3f39da7b7159a0f628cbf746a32253c7e..448bd2c315bf9b7556614d4579eae02c5b049f41 100644 (file)
@@ -1,4 +1,4 @@
-import { shallowRef } from '@vue/reactivity'
+import { ref, shallowRef } from '@vue/reactivity'
 import { nextTick } from '@vue/runtime-dom'
 import { createDynamicComponent } from '../src'
 import { makeRender } from './_utils'
@@ -54,4 +54,42 @@ describe('api: createDynamicComponent', () => {
     await nextTick()
     expect(html()).toBe('<baz></baz><!--dynamic-component-->')
   })
+
+  test('with v-once', async () => {
+    const val = shallowRef<any>(A)
+
+    const { html } = define({
+      setup() {
+        return createDynamicComponent(() => val.value, null, null, true, true)
+      },
+    }).render()
+
+    expect(html()).toBe('AAA<!--dynamic-component-->')
+
+    val.value = B
+    await nextTick()
+    expect(html()).toBe('AAA<!--dynamic-component-->') // still AAA
+  })
+
+  test('fallback with v-once', async () => {
+    const val = shallowRef<any>('button')
+    const id = ref(0)
+    const { html } = define({
+      setup() {
+        return createDynamicComponent(
+          () => val.value,
+          { id: () => id.value },
+          null,
+          true,
+          true,
+        )
+      },
+    }).render()
+
+    expect(html()).toBe('<button id="0"></button><!--dynamic-component-->')
+
+    id.value++
+    await nextTick()
+    expect(html()).toBe('<button id="0"></button><!--dynamic-component-->')
+  })
 })
index a8f55bab6344e61b9f1dd4d25533702d0bd1a04a..a1b1e3e98f3b53517b7e47c18d6a623bafee788e 100644 (file)
@@ -15,7 +15,8 @@ export function createDynamicComponent(
   const frag = __DEV__
     ? new DynamicFragment('dynamic-component')
     : new DynamicFragment()
-  renderEffect(() => {
+
+  const renderFn = () => {
     const value = getter()
     frag.update(
       () =>
@@ -28,6 +29,10 @@ export function createDynamicComponent(
         ),
       value,
     )
-  })
+  }
+
+  if (once) renderFn()
+  else renderEffect(renderFn)
+
   return frag
 }
index a2b2342d93db75c95aaa47fe456c15d5432cb606..27f14f712289f80f96fd5a2d09a38d511284f620 100644 (file)
@@ -479,9 +479,10 @@ export function createComponentWithFallback(
   ;(el as any).$root = isSingleRoot
 
   if (rawProps) {
-    renderEffect(() => {
+    const setFn = () =>
       setDynamicProps(el, [resolveDynamicProps(rawProps as RawProps)])
-    })
+    if (once) setFn()
+    else renderEffect(setFn)
   }
 
   if (rawSlots) {