Explorar el Código

fix(compiler-vapor): properly handling of class and style bindings on SVG (#14383)

close #14382
edison hace 2 meses
padre
commit
301944831b

+ 13 - 2
packages/compiler-vapor/__tests__/transforms/__snapshots__/vBind.spec.ts.snap

@@ -597,12 +597,12 @@ export function render(_ctx) {
 `;
 
 exports[`compiler v-bind > :class w/ svg elements 1`] = `
-"import { setAttr as _setAttr, renderEffect as _renderEffect, template as _template } from 'vue';
+"import { setClass as _setClass, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<svg>", true, 1)
 
 export function render(_ctx) {
   const n0 = t0()
-  _renderEffect(() => _setAttr(n0, "class", _ctx.cls, true))
+  _renderEffect(() => _setClass(n0, _ctx.cls, true))
   return n0
 }"
 `;
@@ -618,6 +618,17 @@ export function render(_ctx) {
 }"
 `;
 
+exports[`compiler v-bind > :style w/ svg elements 1`] = `
+"import { setStyle as _setStyle, renderEffect as _renderEffect, template as _template } from 'vue';
+const t0 = _template("<svg>", true, 1)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _renderEffect(() => _setStyle(n0, _ctx.style))
+  return n0
+}"
+`;
+
 exports[`compiler v-bind > :textContext 1`] = `
 "import { setText as _setText, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div>", true)

+ 10 - 1
packages/compiler-vapor/__tests__/transforms/vBind.spec.ts

@@ -717,7 +717,16 @@ describe('compiler v-bind', () => {
       <svg :class="cls"/>
     `)
     expect(code).matchSnapshot()
-    expect(code).contains('_setAttr(n0, "class", _ctx.cls, true))')
+    // should pass isSVG: true to the helper
+    expect(code).contains('_setClass(n0, _ctx.cls, true))')
+  })
+
+  test(':style w/ svg elements', () => {
+    const { code } = compileWithVBind(`
+      <svg :style="style"/>
+    `)
+    expect(code).matchSnapshot()
+    expect(code).contains('_setStyle(n0, _ctx.style))')
   })
 
   test('v-bind w/ svg elements', () => {

+ 13 - 11
packages/compiler-vapor/src/generators/prop.ts

@@ -177,31 +177,31 @@ function getRuntimeHelper(
   const tagName = tag.toUpperCase()
   const isSVG = isSVGTag(tag)
 
-  // 1. SVG: always attribute
-  if (isSVG) {
-    return extend({ isSVG: true }, helpers.setAttr)
-  }
-
   if (modifier) {
     if (modifier === '.') {
-      return getSpecialHelper(key, tagName) || helpers.setDOMProp
+      return getSpecialHelper(key, tagName, isSVG) || helpers.setDOMProp
     } else {
-      return helpers.setAttr
+      return isSVG ? extend({ isSVG: true }, helpers.setAttr) : helpers.setAttr
     }
   }
 
-  // 2. special handling for value / style / class / textContent /  innerHTML
-  const helper = getSpecialHelper(key, tagName)
+  // 1. special handling for value / style / class / textContent /  innerHTML
+  const helper = getSpecialHelper(key, tagName, isSVG)
   if (helper) {
     return helper
   }
 
-  // 3. Aria DOM properties shared between all Elements in
+  // 2. Aria DOM properties shared between all Elements in
   //    https://developer.mozilla.org/en-US/docs/Web/API/Element
   if (/aria[A-Z]/.test(key)) {
     return helpers.setDOMProp
   }
 
+  // 3. SVG: always attribute
+  if (isSVG) {
+    return extend({ isSVG: true }, helpers.setAttr)
+  }
+
   // 4. respect shouldSetAsAttr used in vdom and setDynamicProp for consistency
   //    also fast path for presence of hyphen (covers data-* and aria-*)
   if (shouldSetAsAttr(tagName, key) || key.includes('-')) {
@@ -216,12 +216,14 @@ function getRuntimeHelper(
 function getSpecialHelper(
   keyName: string,
   tagName: string,
+  isSVG: boolean,
 ): HelperConfig | undefined {
   // special case for 'value' property
   if (keyName === 'value' && canSetValueDirectly(tagName)) {
     return helpers.setValue
   } else if (keyName === 'class') {
-    return helpers.setClass
+    // for svg, class should be set as attribute
+    return extend({ isSVG }, helpers.setClass)
   } else if (keyName === 'style') {
     return helpers.setStyle
   } else if (keyName === 'innerHTML') {