فهرست منبع

fix(vapor): component emits vdom interop

daiwei 10 ماه پیش
والد
کامیت
26dbd3c902

+ 32 - 1
packages/runtime-vapor/__tests__/componentEmits.spec.ts

@@ -4,12 +4,18 @@
 // ./rendererAttrsFallthrough.spec.ts.
 
 import {
+  createApp,
+  h,
   isEmitListener,
   nextTick,
   onBeforeUnmount,
   toHandlers,
 } from '@vue/runtime-dom'
-import { createComponent, defineVaporComponent } from '../src'
+import {
+  createComponent,
+  defineVaporComponent,
+  vaporInteropPlugin,
+} from '../src'
 import { makeRender } from './_utils'
 
 const define = makeRender()
@@ -425,3 +431,28 @@ describe('component: emit', () => {
     expect(fn).not.toHaveBeenCalled()
   })
 })
+
+describe('vdom interop', () => {
+  test('vdom parent > vapor child', () => {
+    const VaporChild = defineVaporComponent({
+      emits: ['click'],
+      setup(_, { emit }) {
+        emit('click')
+        return []
+      },
+    })
+
+    const fn = vi.fn()
+    const App = {
+      setup() {
+        return () => h(VaporChild as any, { onClick: fn })
+      },
+    }
+
+    const root = document.createElement('div')
+    createApp(App).use(vaporInteropPlugin).mount(root)
+
+    // fn should be called once
+    expect(fn).toHaveBeenCalledTimes(1)
+  })
+})

+ 5 - 1
packages/runtime-vapor/src/componentEmits.ts

@@ -46,7 +46,11 @@ function propGetter(rawProps: Record<string, any>, key: string) {
     let i = dynamicSources.length
     while (i--) {
       const source = resolveSource(dynamicSources[i])
-      if (hasOwn(source, key)) return resolveSource(source[key])
+      if (hasOwn(source, key))
+        // for props passed from VDOM component, no need to resolve
+        return dynamicSources.__interop
+          ? source[key]
+          : resolveSource(source[key])
     }
   }
   return rawProps[key] && resolveSource(rawProps[key])

+ 1 - 1
packages/runtime-vapor/src/componentProps.ts

@@ -26,7 +26,7 @@ import { renderEffect } from './renderEffect'
 
 export type RawProps = Record<string, () => unknown> & {
   // generated by compiler for :[key]="x" or v-bind="x"
-  $?: DynamicPropsSource[]
+  $?: DynamicPropsSource[] & { __interop?: boolean }
 }
 
 export type DynamicPropsSource =

+ 1 - 1
packages/runtime-vapor/src/vdomInterop.ts

@@ -52,7 +52,7 @@ const vaporInteropImpl: Omit<
     const instance = (vnode.component = createComponent(
       vnode.type as any as VaporComponent,
       {
-        $: [() => propsRef.value],
+        $: extend([() => propsRef.value], { __interop: true }),
       } as RawProps,
       {
         _: slotsRef, // pass the slots ref