Skip to content

Commit ea3efa0

Browse files
committedSep 27, 2024··
fix(custom-element): properly set kebab-case props on Vue custom elements
close #12030 close #12032
1 parent a77b959 commit ea3efa0

File tree

2 files changed

+29
-11
lines changed

2 files changed

+29
-11
lines changed
 

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

+15
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,21 @@ describe('defineCustomElement', () => {
223223
expect(e.getAttribute('baz-qux')).toBe('four')
224224
})
225225

226+
test('props via hyphen property', async () => {
227+
const Comp = defineCustomElement({
228+
props: {
229+
fooBar: Boolean,
230+
},
231+
render() {
232+
return 'Comp'
233+
},
234+
})
235+
customElements.define('my-el-comp', Comp)
236+
render(h('my-el-comp', { 'foo-bar': true }), container)
237+
const el = container.children[0]
238+
expect((el as any).outerHTML).toBe('<my-el-comp foo-bar=""></my-el-comp>')
239+
})
240+
226241
test('attribute -> prop type casting', async () => {
227242
const E = defineCustomElement({
228243
props: {

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

+14-11
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ import { patchStyle } from './modules/style'
33
import { patchAttr } from './modules/attrs'
44
import { patchDOMProp } from './modules/props'
55
import { patchEvent } from './modules/events'
6-
import { isFunction, isModelListener, isOn, isString } from '@vue/shared'
6+
import {
7+
camelize,
8+
isFunction,
9+
isModelListener,
10+
isOn,
11+
isString,
12+
} from '@vue/shared'
713
import type { RendererOptions } from '@vue/runtime-core'
814
import type { VueElement } from './apiCustomElement'
915

@@ -51,6 +57,12 @@ export const patchProp: DOMRendererOptions['patchProp'] = (
5157
) {
5258
patchAttr(el, key, nextValue, isSVG, parentComponent, key !== 'value')
5359
}
60+
} else if (
61+
// #11081 force set props for possible async custom element
62+
(el as VueElement)._isVueCE &&
63+
(/[A-Z]/.test(key) || !isString(nextValue))
64+
) {
65+
patchDOMProp(el, camelize(key), nextValue, parentComponent)
5466
} else {
5567
// special case for <input v-model type="checkbox"> with
5668
// :true-value & :false-value
@@ -128,14 +140,5 @@ function shouldSetAsProp(
128140
return false
129141
}
130142

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
143+
return key in el
141144
}

0 commit comments

Comments
 (0)
Please sign in to comment.