Skip to content

Commit 55382ae

Browse files
authoredNov 11, 2022
fix(custom-elements): define declared properties in constructor (#5328)
1 parent 89f37ce commit 55382ae

File tree

2 files changed

+58
-20
lines changed

2 files changed

+58
-20
lines changed
 

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

+24
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,30 @@ describe('defineCustomElement', () => {
215215
expect(el.hasAttribute('not-prop')).toBe(false)
216216
})
217217

218+
test('handle properties set before connecting', () => {
219+
const obj = { a: 1 }
220+
const E = defineCustomElement({
221+
props: {
222+
foo: String,
223+
post: Object
224+
},
225+
setup(props) {
226+
expect(props.foo).toBe('hello')
227+
expect(props.post).toBe(obj)
228+
},
229+
render() {
230+
return JSON.stringify(this.post)
231+
}
232+
})
233+
customElements.define('my-el-preconnect', E)
234+
const el = document.createElement('my-el-preconnect') as any
235+
el.foo = 'hello'
236+
el.post = obj
237+
238+
container.appendChild(el)
239+
expect(el.shadowRoot.innerHTML).toBe(JSON.stringify(obj))
240+
})
241+
218242
// https://github.com/vuejs/core/issues/6163
219243
test('handle components with no props', async () => {
220244
const E = defineCustomElement({

‎packages/runtime-dom/src/apiCustomElement.ts

+34-20
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ export class VueElement extends BaseClass {
186186
)
187187
}
188188
this.attachShadow({ mode: 'open' })
189+
if (!(this._def as ComponentOptions).__asyncLoader) {
190+
// for sync component defs we can immediately resolve props
191+
this._resolveProps(this._def)
192+
}
189193
}
190194
}
191195

@@ -227,9 +231,8 @@ export class VueElement extends BaseClass {
227231
}
228232
}).observe(this, { attributes: true })
229233

230-
const resolve = (def: InnerComponentDef) => {
234+
const resolve = (def: InnerComponentDef, isAsync = false) => {
231235
const { props, styles } = def
232-
const declaredPropKeys = isArray(props) ? props : Object.keys(props || {})
233236

234237
// cast Number-type props set before resolve
235238
let numberProps
@@ -248,23 +251,10 @@ export class VueElement extends BaseClass {
248251
}
249252
this._numberProps = numberProps
250253

251-
// check if there are props set pre-upgrade or connect
252-
for (const key of Object.keys(this)) {
253-
if (key[0] !== '_' && declaredPropKeys.includes(key)) {
254-
this._setProp(key, this[key as keyof this], true, false)
255-
}
256-
}
257-
258-
// defining getter/setters on prototype
259-
for (const key of declaredPropKeys.map(camelize)) {
260-
Object.defineProperty(this, key, {
261-
get() {
262-
return this._getProp(key)
263-
},
264-
set(val) {
265-
this._setProp(key, val)
266-
}
267-
})
254+
if (isAsync) {
255+
// defining getter/setters on prototype
256+
// for sync defs, this already happened in the constructor
257+
this._resolveProps(def)
268258
}
269259

270260
// apply CSS
@@ -276,12 +266,36 @@ export class VueElement extends BaseClass {
276266

277267
const asyncDef = (this._def as ComponentOptions).__asyncLoader
278268
if (asyncDef) {
279-
asyncDef().then(resolve)
269+
asyncDef().then(def => resolve(def, true))
280270
} else {
281271
resolve(this._def)
282272
}
283273
}
284274

275+
private _resolveProps(def: InnerComponentDef) {
276+
const { props } = def
277+
const declaredPropKeys = isArray(props) ? props : Object.keys(props || {})
278+
279+
// check if there are props set pre-upgrade or connect
280+
for (const key of Object.keys(this)) {
281+
if (key[0] !== '_' && declaredPropKeys.includes(key)) {
282+
this._setProp(key, this[key as keyof this], true, false)
283+
}
284+
}
285+
286+
// defining getter/setters on prototype
287+
for (const key of declaredPropKeys.map(camelize)) {
288+
Object.defineProperty(this, key, {
289+
get() {
290+
return this._getProp(key)
291+
},
292+
set(val) {
293+
this._setProp(key, val)
294+
}
295+
})
296+
}
297+
}
298+
285299
protected _setAttr(key: string) {
286300
let value = this.getAttribute(key)
287301
const camelKey = camelize(key)

0 commit comments

Comments
 (0)
Please sign in to comment.