Explorar el Código

fix(compiler-sfc): properly handle shorthand property in template expressions

fix #12566
Evan You hace 4 años
padre
commit
9b9f2bf1c8

+ 16 - 18
packages/compiler-sfc/src/prefixIdentifiers.ts

@@ -1,7 +1,7 @@
 import MagicString from 'magic-string'
 import { parseExpression, ParserOptions, ParserPlugin } from '@babel/parser'
 import { makeMap } from 'shared/util'
-import { walkIdentifiers } from './babelUtils'
+import { isStaticProperty, walkIdentifiers } from './babelUtils'
 import { BindingMetadata } from './types'
 
 const doNotPrefix = makeMap(
@@ -39,18 +39,28 @@ export function prefixIdentifiers(
 
   walkIdentifiers(
     ast,
-    ident => {
+    (ident, parent) => {
       const { name } = ident
       if (doNotPrefix(name)) {
         return
       }
 
-      if (!isScriptSetup) {
-        s.prependRight(ident.start!, '_vm.')
-        return
+      let prefix = `_vm.`
+      if (isScriptSetup) {
+        const type = bindings[name]
+        if (type && type.startsWith('setup')) {
+          prefix = `_setup.`
+        }
       }
 
-      s.overwrite(ident.start!, ident.end!, rewriteIdentifier(name, bindings))
+      if (isStaticProperty(parent) && parent.shorthand) {
+        // property shorthand like { foo }, we need to add the key since
+        // we rewrite the value
+        // { foo } -> { foo: _vm.foo }
+        s.appendLeft(ident.end!, `: ${prefix}${name}`)
+      } else {
+        s.prependRight(ident.start!, prefix)
+      }
     },
     node => {
       if (node.type === 'WithStatement') {
@@ -70,15 +80,3 @@ export function prefixIdentifiers(
 
   return s.toString()
 }
-
-export function rewriteIdentifier(
-  name: string,
-  bindings: BindingMetadata
-): string {
-  const type = bindings[name]
-  if (type && type.startsWith('setup')) {
-    return `_setup.${name}`
-  } else {
-    return `_vm.${name}`
-  }
-}

+ 3 - 2
packages/compiler-sfc/test/prefixIdentifiers.spec.ts

@@ -7,7 +7,7 @@ const toFn = (source: string) => `function render(){${source}\n}`
 
 it('should work', () => {
   const { render } = compile(`<div id="app">
-  <div>{{ foo }}</div>
+  <div :style="{ color }">{{ foo }}</div>
   <p v-for="i in list">{{ i }}</p>
   <foo inline-template>
     <div>{{ bar }}</div>
@@ -22,6 +22,7 @@ it('should work', () => {
   expect(result).not.toMatch(`_vm._c`)
   expect(result).toMatch(`_vm.foo`)
   expect(result).toMatch(`_vm.list`)
+  expect(result).toMatch(`{ color: _vm.color }`)
   expect(result).not.toMatch(`_vm.i`)
   expect(result).not.toMatch(`with (this)`)
 
@@ -33,7 +34,7 @@ it('should work', () => {
         \\"div\\",
         { attrs: { id: \\"app\\" } },
         [
-          _c(\\"div\\", [_vm._v(_vm._s(_vm.foo))]),
+          _c(\\"div\\", { style: { color: _vm.color } }, [_vm._v(_vm._s(_vm.foo))]),
           _vm._v(\\" \\"),
           _vm._l(_vm.list, function (i) {
             return _c(\\"p\\", [_vm._v(_vm._s(i))])