diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts
index 60b51de3893..777f9677d04 100644
--- a/packages/runtime-dom/__tests__/customElement.spec.ts
+++ b/packages/runtime-dom/__tests__/customElement.spec.ts
@@ -191,13 +191,21 @@ describe('defineCustomElement', () => {
test('handling properties set before upgrading', () => {
const E = defineCustomElement({
- props: ['foo'],
+ props: {
+ foo: String,
+ dataAge: Number
+ },
+ setup(props) {
+ expect(props.foo).toBe('hello')
+ expect(props.dataAge).toBe(5)
+ },
render() {
return `foo: ${this.foo}`
}
})
const el = document.createElement('my-el-upgrade') as any
el.foo = 'hello'
+ el.dataset.age = 5
container.appendChild(el)
customElements.define('my-el-upgrade', E)
expect(el.shadowRoot.innerHTML).toBe(`foo: hello`)
@@ -363,10 +371,10 @@ describe('defineCustomElement', () => {
// should inject styles
expect(e1.shadowRoot!.innerHTML).toBe(
- `
hello
`
+ `hello
`
)
expect(e2.shadowRoot!.innerHTML).toBe(
- `world
`
+ `world
`
)
// attr
@@ -374,7 +382,7 @@ describe('defineCustomElement', () => {
await nextTick()
expect((e1 as any).msg).toBe('attr')
expect(e1.shadowRoot!.innerHTML).toBe(
- `attr
`
+ `attr
`
)
// props
@@ -382,7 +390,7 @@ describe('defineCustomElement', () => {
;(e1 as any).msg = 'prop'
expect(e1.getAttribute('msg')).toBe('prop')
expect(e1.shadowRoot!.innerHTML).toBe(
- `prop
`
+ `prop
`
)
})
@@ -391,6 +399,9 @@ describe('defineCustomElement', () => {
defineAsyncComponent(() => {
return Promise.resolve({
props: ['msg'],
+ setup(props) {
+ expect(typeof props.msg).toBe('string')
+ },
render(this: any) {
return h('div', this.msg)
}
@@ -429,6 +440,9 @@ describe('defineCustomElement', () => {
defineAsyncComponent(() => {
return Promise.resolve({
props: { n: Number },
+ setup(props) {
+ expect(props.n).toBe(20)
+ },
render(this: any) {
return h('div', this.n + ',' + typeof this.n)
}
diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts
index a532da4c6c7..5127e4a47f5 100644
--- a/packages/runtime-dom/src/apiCustomElement.ts
+++ b/packages/runtime-dom/src/apiCustomElement.ts
@@ -180,7 +180,6 @@ export class VueElement extends BaseClass {
this._connected = true
if (!this._instance) {
this._resolveDef()
- this._update()
}
}
@@ -231,17 +230,15 @@ export class VueElement extends BaseClass {
}
}
}
- if (numberProps) {
- this._numberProps = numberProps
- this._update()
- }
+ this._numberProps = numberProps
// check if there are props set pre-upgrade or connect
for (const key of Object.keys(this)) {
if (key[0] !== '_') {
- this._setProp(key, this[key as keyof this])
+ this._setProp(key, this[key as keyof this], true, false)
}
}
+
// defining getter/setters on prototype
for (const key of rawKeys.map(camelize)) {
Object.defineProperty(this, key, {
@@ -253,7 +250,12 @@ export class VueElement extends BaseClass {
}
})
}
+
+ // apply CSS
this._applyStyles(styles)
+
+ // initial render
+ this._update()
}
const asyncDef = (this._def as ComponentOptions).__asyncLoader
@@ -282,10 +284,15 @@ export class VueElement extends BaseClass {
/**
* @internal
*/
- protected _setProp(key: string, val: any, shouldReflect = true) {
+ protected _setProp(
+ key: string,
+ val: any,
+ shouldReflect = true,
+ shouldUpdate = true
+ ) {
if (val !== this._props[key]) {
this._props[key] = val
- if (this._instance) {
+ if (shouldUpdate && this._instance) {
this._update()
}
// reflect