Skip to content

Commit 4b7f76e

Browse files
committed
fix(custom-element): fix custom element props access on initial render
ref: #4792
1 parent 6916d72 commit 4b7f76e

File tree

2 files changed

+34
-13
lines changed

2 files changed

+34
-13
lines changed

packages/runtime-dom/__tests__/customElement.spec.ts

+19-5
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,21 @@ describe('defineCustomElement', () => {
191191

192192
test('handling properties set before upgrading', () => {
193193
const E = defineCustomElement({
194-
props: ['foo'],
194+
props: {
195+
foo: String,
196+
dataAge: Number
197+
},
198+
setup(props) {
199+
expect(props.foo).toBe('hello')
200+
expect(props.dataAge).toBe(5)
201+
},
195202
render() {
196203
return `foo: ${this.foo}`
197204
}
198205
})
199206
const el = document.createElement('my-el-upgrade') as any
200207
el.foo = 'hello'
208+
el.dataset.age = 5
201209
container.appendChild(el)
202210
customElements.define('my-el-upgrade', E)
203211
expect(el.shadowRoot.innerHTML).toBe(`foo: hello`)
@@ -363,26 +371,26 @@ describe('defineCustomElement', () => {
363371

364372
// should inject styles
365373
expect(e1.shadowRoot!.innerHTML).toBe(
366-
`<div>hello</div><style>div { color: red }</style>`
374+
`<style>div { color: red }</style><div>hello</div>`
367375
)
368376
expect(e2.shadowRoot!.innerHTML).toBe(
369-
`<div>world</div><style>div { color: red }</style>`
377+
`<style>div { color: red }</style><div>world</div>`
370378
)
371379

372380
// attr
373381
e1.setAttribute('msg', 'attr')
374382
await nextTick()
375383
expect((e1 as any).msg).toBe('attr')
376384
expect(e1.shadowRoot!.innerHTML).toBe(
377-
`<div>attr</div><style>div { color: red }</style>`
385+
`<style>div { color: red }</style><div>attr</div>`
378386
)
379387

380388
// props
381389
expect(`msg` in e1).toBe(true)
382390
;(e1 as any).msg = 'prop'
383391
expect(e1.getAttribute('msg')).toBe('prop')
384392
expect(e1.shadowRoot!.innerHTML).toBe(
385-
`<div>prop</div><style>div { color: red }</style>`
393+
`<style>div { color: red }</style><div>prop</div>`
386394
)
387395
})
388396

@@ -391,6 +399,9 @@ describe('defineCustomElement', () => {
391399
defineAsyncComponent(() => {
392400
return Promise.resolve({
393401
props: ['msg'],
402+
setup(props) {
403+
expect(typeof props.msg).toBe('string')
404+
},
394405
render(this: any) {
395406
return h('div', this.msg)
396407
}
@@ -429,6 +440,9 @@ describe('defineCustomElement', () => {
429440
defineAsyncComponent(() => {
430441
return Promise.resolve({
431442
props: { n: Number },
443+
setup(props) {
444+
expect(props.n).toBe(20)
445+
},
432446
render(this: any) {
433447
return h('div', this.n + ',' + typeof this.n)
434448
}

packages/runtime-dom/src/apiCustomElement.ts

+15-8
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ export class VueElement extends BaseClass {
180180
this._connected = true
181181
if (!this._instance) {
182182
this._resolveDef()
183-
this._update()
184183
}
185184
}
186185

@@ -231,17 +230,15 @@ export class VueElement extends BaseClass {
231230
}
232231
}
233232
}
234-
if (numberProps) {
235-
this._numberProps = numberProps
236-
this._update()
237-
}
233+
this._numberProps = numberProps
238234

239235
// check if there are props set pre-upgrade or connect
240236
for (const key of Object.keys(this)) {
241237
if (key[0] !== '_') {
242-
this._setProp(key, this[key as keyof this])
238+
this._setProp(key, this[key as keyof this], true, false)
243239
}
244240
}
241+
245242
// defining getter/setters on prototype
246243
for (const key of rawKeys.map(camelize)) {
247244
Object.defineProperty(this, key, {
@@ -253,7 +250,12 @@ export class VueElement extends BaseClass {
253250
}
254251
})
255252
}
253+
254+
// apply CSS
256255
this._applyStyles(styles)
256+
257+
// initial render
258+
this._update()
257259
}
258260

259261
const asyncDef = (this._def as ComponentOptions).__asyncLoader
@@ -282,10 +284,15 @@ export class VueElement extends BaseClass {
282284
/**
283285
* @internal
284286
*/
285-
protected _setProp(key: string, val: any, shouldReflect = true) {
287+
protected _setProp(
288+
key: string,
289+
val: any,
290+
shouldReflect = true,
291+
shouldUpdate = true
292+
) {
286293
if (val !== this._props[key]) {
287294
this._props[key] = val
288-
if (this._instance) {
295+
if (shouldUpdate && this._instance) {
289296
this._update()
290297
}
291298
// reflect

0 commit comments

Comments
 (0)