From: Evan You Date: Sat, 9 Oct 2021 22:34:49 +0000 (-0400) Subject: fix(custom-element): fix initial attr type casting for programmtically created elements X-Git-Tag: v3.2.21~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3ca83179d1a798f65e4e70215c511e2f1b64adb6;p=thirdparty%2Fvuejs%2Fcore.git fix(custom-element): fix initial attr type casting for programmtically created elements fix #4772 --- diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 7e69ec28ef..60b51de389 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -172,6 +172,23 @@ describe('defineCustomElement', () => { expect(e.shadowRoot!.innerHTML).toBe(`20 number true boolean 2e1 string`) }) + // #4772 + test('attr casting w/ programmatic creation', () => { + const E = defineCustomElement({ + props: { + foo: Number + }, + render() { + return `foo type: ${typeof this.foo}` + } + }) + customElements.define('my-element-programmatic', E) + const el = document.createElement('my-element-programmatic') as any + el.setAttribute('foo', '123') + container.appendChild(el) + expect(el.shadowRoot.innerHTML).toBe(`foo type: number`) + }) + test('handling properties set before upgrading', () => { const E = defineCustomElement({ props: ['foo'], diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index f72b8765f6..a532da4c6c 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -174,17 +174,6 @@ export class VueElement extends BaseClass { } this.attachShadow({ mode: 'open' }) } - - // set initial attrs - for (let i = 0; i < this.attributes.length; i++) { - this._setAttr(this.attributes[i].name) - } - // watch future attr changes - new MutationObserver(mutations => { - for (const m of mutations) { - this._setAttr(m.attributeName!) - } - }).observe(this, { attributes: true }) } connectedCallback() { @@ -212,9 +201,21 @@ export class VueElement extends BaseClass { if (this._resolved) { return } + this._resolved = true + + // set initial attrs + for (let i = 0; i < this.attributes.length; i++) { + this._setAttr(this.attributes[i].name) + } + + // watch future attr changes + new MutationObserver(mutations => { + for (const m of mutations) { + this._setAttr(m.attributeName!) + } + }).observe(this, { attributes: true }) const resolve = (def: InnerComponentDef) => { - this._resolved = true const { props, styles } = def const hasOptions = !isArray(props) const rawKeys = props ? (hasOptions ? Object.keys(props) : props) : []