Procházet zdrojové kódy

fix(custom-element): support early-set domProps for async custom elements

close #11081
close #11082
Evan You před 1 rokem
rodič
revize
a07e7bf553

+ 35 - 0
packages/runtime-dom/__tests__/customElement.spec.ts

@@ -1206,4 +1206,39 @@ describe('defineCustomElement', () => {
       'hello',
     )
   })
+
+  // #11081
+  test('Props can be casted when mounting custom elements in component rendering functions', async () => {
+    const E = defineCustomElement(
+      defineAsyncComponent(() =>
+        Promise.resolve({
+          props: ['fooValue'],
+          setup(props) {
+            expect(props.fooValue).toBe('fooValue')
+            return () => h('div', props.fooValue)
+          },
+        }),
+      ),
+    )
+    customElements.define('my-el-async-4', E)
+    const R = defineComponent({
+      setup() {
+        const fooValue = ref('fooValue')
+        return () => {
+          return h('div', null, [
+            h('my-el-async-4', {
+              fooValue: fooValue.value,
+            }),
+          ])
+        }
+      },
+    })
+
+    const app = createApp(R)
+    app.mount(container)
+    await new Promise(r => setTimeout(r))
+    const e = container.querySelector('my-el-async-4') as VueElement
+    expect(e.shadowRoot!.innerHTML).toBe(`<div>fooValue</div>`)
+    app.unmount()
+  })
 })

+ 5 - 4
packages/runtime-dom/src/apiCustomElement.ts

@@ -200,6 +200,7 @@ export class VueElement
   extends BaseClass
   implements ComponentCustomElementInterface
 {
+  _isVueCE = true
   /**
    * @internal
    */
@@ -208,6 +209,10 @@ export class VueElement
    * @internal
    */
   _app: App | null = null
+  /**
+   * @internal
+   */
+  _root: Element | ShadowRoot
   /**
    * @internal
    */
@@ -228,10 +233,6 @@ export class VueElement
    */
   private _childStyles?: Map<string, HTMLStyleElement[]>
   private _ob?: MutationObserver | null = null
-  /**
-   * @internal
-   */
-  public _root: Element | ShadowRoot
   private _slots?: Record<string, Node[]>
 
   constructor(

+ 11 - 1
packages/runtime-dom/src/patchProp.ts

@@ -5,6 +5,7 @@ import { patchDOMProp } from './modules/props'
 import { patchEvent } from './modules/events'
 import { isFunction, isModelListener, isOn, isString } from '@vue/shared'
 import type { RendererOptions } from '@vue/runtime-core'
+import type { VueElement } from './apiCustomElement'
 
 const isNativeOn = (key: string) =>
   key.charCodeAt(0) === 111 /* o */ &&
@@ -127,5 +128,14 @@ function shouldSetAsProp(
     return false
   }
 
-  return key in el
+  if (key in el) {
+    return true
+  }
+
+  // #11081 force set props for possible async custom element
+  if ((el as VueElement)._isVueCE && (/[A-Z]/.test(key) || !isString(value))) {
+    return true
+  }
+
+  return false
 }