]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(custom-element): properly set kebab-case props on Vue custom elements
authorEvan You <evan@vuejs.org>
Fri, 27 Sep 2024 01:25:00 +0000 (09:25 +0800)
committerEvan You <evan@vuejs.org>
Fri, 27 Sep 2024 01:25:00 +0000 (09:25 +0800)
close #12030
close #12032

packages/runtime-dom/__tests__/customElement.spec.ts
packages/runtime-dom/src/patchProp.ts

index 51113edef69a33984010fa6b36ba6a78135014af..ef5051f42f7567fe63973c13b62fbf0eeb132b3b 100644 (file)
@@ -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('<my-el-comp foo-bar=""></my-el-comp>')
+    })
+
     test('attribute -> prop type casting', async () => {
       const E = defineCustomElement({
         props: {
index 98b69967c71b7607187b7b2b44b19fc59aa7119f..5814e77c4f820d6288ea8213bcce9dee4b3b9715 100644 (file)
@@ -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 <input v-model type="checkbox"> 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
 }