diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 51113edef69..ef5051f42f7 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -223,6 +223,21 @@ describe('defineCustomElement', () => { expect(e.getAttribute('baz-qux')).toBe('four') }) + test('props via hyphen property', async () => { + const Comp = defineCustomElement({ + props: { + fooBar: Boolean, + }, + render() { + return 'Comp' + }, + }) + customElements.define('my-el-comp', Comp) + render(h('my-el-comp', { 'foo-bar': true }), container) + const el = container.children[0] + expect((el as any).outerHTML).toBe('') + }) + test('attribute -> prop type casting', async () => { const E = defineCustomElement({ props: { diff --git a/packages/runtime-dom/src/patchProp.ts b/packages/runtime-dom/src/patchProp.ts index 98b69967c71..5814e77c4f8 100644 --- a/packages/runtime-dom/src/patchProp.ts +++ b/packages/runtime-dom/src/patchProp.ts @@ -3,7 +3,13 @@ import { patchStyle } from './modules/style' import { patchAttr } from './modules/attrs' import { patchDOMProp } from './modules/props' import { patchEvent } from './modules/events' -import { isFunction, isModelListener, isOn, isString } from '@vue/shared' +import { + camelize, + isFunction, + isModelListener, + isOn, + isString, +} from '@vue/shared' import type { RendererOptions } from '@vue/runtime-core' import type { VueElement } from './apiCustomElement' @@ -51,6 +57,12 @@ export const patchProp: DOMRendererOptions['patchProp'] = ( ) { patchAttr(el, key, nextValue, isSVG, parentComponent, key !== 'value') } + } else if ( + // #11081 force set props for possible async custom element + (el as VueElement)._isVueCE && + (/[A-Z]/.test(key) || !isString(nextValue)) + ) { + patchDOMProp(el, camelize(key), nextValue, parentComponent) } else { // special case for with // :true-value & :false-value @@ -128,14 +140,5 @@ function shouldSetAsProp( return false } - if (key in el) { - return true - } - - // #11081 force set props for possible async custom element - if ((el as VueElement)._isVueCE && (/[A-Z]/.test(key) || !isString(value))) { - return true - } - - return false + return key in el }