From: Evan You Date: Thu, 8 Aug 2024 08:26:48 +0000 (+0800) Subject: fix(custom-element): support early-set domProps for async custom elements X-Git-Tag: v3.5.0-beta.1~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a07e7bf5536a6b3db70ba9bb1c3f366dac1bf5a0;p=thirdparty%2Fvuejs%2Fcore.git fix(custom-element): support early-set domProps for async custom elements close #11081 close #11082 --- diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 38af0e2a63..da0d614f65 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/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(`
fooValue
`) + app.unmount() + }) }) diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index af6063cdb0..aa191ba6c7 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/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 private _ob?: MutationObserver | null = null - /** - * @internal - */ - public _root: Element | ShadowRoot private _slots?: Record constructor( diff --git a/packages/runtime-dom/src/patchProp.ts b/packages/runtime-dom/src/patchProp.ts index f3ef14ee83..98b69967c7 100644 --- a/packages/runtime-dom/src/patchProp.ts +++ b/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 }