Skip to content

Commit a07e7bf

Browse files
committed
fix(custom-element): support early-set domProps for async custom elements
close #11081 close #11082
1 parent 9b531d5 commit a07e7bf

File tree

3 files changed

+51
-5
lines changed

3 files changed

+51
-5
lines changed

Diff for: packages/runtime-dom/__tests__/customElement.spec.ts

+35
Original file line numberDiff line numberDiff line change
@@ -1206,4 +1206,39 @@ describe('defineCustomElement', () => {
12061206
'hello',
12071207
)
12081208
})
1209+
1210+
// #11081
1211+
test('Props can be casted when mounting custom elements in component rendering functions', async () => {
1212+
const E = defineCustomElement(
1213+
defineAsyncComponent(() =>
1214+
Promise.resolve({
1215+
props: ['fooValue'],
1216+
setup(props) {
1217+
expect(props.fooValue).toBe('fooValue')
1218+
return () => h('div', props.fooValue)
1219+
},
1220+
}),
1221+
),
1222+
)
1223+
customElements.define('my-el-async-4', E)
1224+
const R = defineComponent({
1225+
setup() {
1226+
const fooValue = ref('fooValue')
1227+
return () => {
1228+
return h('div', null, [
1229+
h('my-el-async-4', {
1230+
fooValue: fooValue.value,
1231+
}),
1232+
])
1233+
}
1234+
},
1235+
})
1236+
1237+
const app = createApp(R)
1238+
app.mount(container)
1239+
await new Promise(r => setTimeout(r))
1240+
const e = container.querySelector('my-el-async-4') as VueElement
1241+
expect(e.shadowRoot!.innerHTML).toBe(`<div>fooValue</div>`)
1242+
app.unmount()
1243+
})
12091244
})

Diff for: packages/runtime-dom/src/apiCustomElement.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ export class VueElement
200200
extends BaseClass
201201
implements ComponentCustomElementInterface
202202
{
203+
_isVueCE = true
203204
/**
204205
* @internal
205206
*/
@@ -208,6 +209,10 @@ export class VueElement
208209
* @internal
209210
*/
210211
_app: App | null = null
212+
/**
213+
* @internal
214+
*/
215+
_root: Element | ShadowRoot
211216
/**
212217
* @internal
213218
*/
@@ -228,10 +233,6 @@ export class VueElement
228233
*/
229234
private _childStyles?: Map<string, HTMLStyleElement[]>
230235
private _ob?: MutationObserver | null = null
231-
/**
232-
* @internal
233-
*/
234-
public _root: Element | ShadowRoot
235236
private _slots?: Record<string, Node[]>
236237

237238
constructor(

Diff for: packages/runtime-dom/src/patchProp.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { patchDOMProp } from './modules/props'
55
import { patchEvent } from './modules/events'
66
import { isFunction, isModelListener, isOn, isString } from '@vue/shared'
77
import type { RendererOptions } from '@vue/runtime-core'
8+
import type { VueElement } from './apiCustomElement'
89

910
const isNativeOn = (key: string) =>
1011
key.charCodeAt(0) === 111 /* o */ &&
@@ -127,5 +128,14 @@ function shouldSetAsProp(
127128
return false
128129
}
129130

130-
return key in el
131+
if (key in el) {
132+
return true
133+
}
134+
135+
// #11081 force set props for possible async custom element
136+
if ((el as VueElement)._isVueCE && (/[A-Z]/.test(key) || !isString(value))) {
137+
return true
138+
}
139+
140+
return false
131141
}

0 commit comments

Comments
 (0)