Просмотр исходного кода

only treat binding as domProps on specific elements (fix #4233)

Evan You 9 лет назад
Родитель
Сommit
9a742cb423

+ 1 - 1
flow/compiler.js

@@ -7,7 +7,7 @@ declare type CompilerOptions = {
   directives?: { [key: string]: Function }; // platform specific directives
   isUnaryTag?: (tag: string) => ?boolean; // check if a tag is unary for the platform
   isReservedTag?: (tag: string) => ?boolean; // check if a tag is a native for the platform
-  mustUseProp?: (attr: string) => ?boolean; // check if an attribute should be bound as a property
+  mustUseProp?: (tag: string, attr: string) => ?boolean; // check if an attribute should be bound as a property
   isPreTag?: (attr: string) => ?boolean; // check if a tag needs to preserve whitespace
   getTagNamespace?: (tag: string) => ?string; // check the namespace for a tag
   transforms?: Array<Function>; // a list of transforms on parsed AST before codegen

+ 1 - 5
src/compiler/directives/bind.js

@@ -2,11 +2,7 @@
 
 export default function bind (el: ASTElement, dir: ASTDirective) {
   el.wrapData = (code: string) => {
-    return `_b(${
-      code
-    },${
-      dir.value
-    }${
+    return `_b(${code},'${el.tag}',${dir.value}${
       dir.modifiers && dir.modifiers.prop ? ',true' : ''
     })`
   }

+ 1 - 1
src/compiler/parser/index.js

@@ -379,7 +379,7 @@ function processAttrs (el) {
           name = camelize(name)
           if (name === 'innerHtml') name = 'innerHTML'
         }
-        if (isProp || platformMustUseProp(name)) {
+        if (isProp || platformMustUseProp(el.tag, name)) {
           addProp(el, name, value)
         } else {
           addAttr(el, name, value)

+ 1 - 1
src/core/config.js

@@ -14,7 +14,7 @@ export type Config = {
   isReservedTag: (x?: string) => boolean;
   isUnknownElement: (x?: string) => boolean;
   getTagNamespace: (x?: string) => string | void;
-  mustUseProp: (x?: string) => boolean;
+  mustUseProp: (tag?: string, x?: string) => boolean;
   // internal
   _assetTypes: Array<string>;
   _lifecycleHooks: Array<string>;

+ 2 - 1
src/core/instance/render.js

@@ -201,6 +201,7 @@ export function renderMixin (Vue: Class<Component>) {
   // apply v-bind object
   Vue.prototype._b = function bindProps (
     data: any,
+    tag: string,
     value: any,
     asProp?: boolean
   ): VNodeData {
@@ -218,7 +219,7 @@ export function renderMixin (Vue: Class<Component>) {
           if (key === 'class' || key === 'style') {
             data[key] = value[key]
           } else {
-            const hash = asProp || config.mustUseProp(key)
+            const hash = asProp || config.mustUseProp(tag, key)
               ? data.domProps || (data.domProps = {})
               : data.attrs || (data.attrs = {})
             hash[key] = value[key]

+ 8 - 1
src/platforms/web/util/attrs.js

@@ -3,7 +3,14 @@
 import { makeMap } from 'shared/util'
 
 // attributes that should be using props for binding
-export const mustUseProp = makeMap('value,selected,checked,muted')
+export const mustUseProp = (tag: string, attr: string): boolean => {
+  return (
+    (attr === 'value' && (tag === 'input' || tag === 'textarea' || tag === 'option')) ||
+    (attr === 'selected' && tag === 'option') ||
+    (attr === 'checked' && tag === 'input') ||
+    (attr === 'muted' && tag === 'video')
+  )
+}
 
 export const isEnumeratedAttr = makeMap('contenteditable,draggable,spellcheck')
 

+ 8 - 2
test/unit/modules/compiler/codegen.spec.js

@@ -84,7 +84,7 @@ describe('codegen', () => {
   it('generate v-bind directive', () => {
     assertCodegen(
       '<p v-bind="test"></p>',
-      `with(this){return _h('p',_b({},test))}`
+      `with(this){return _h('p',_b({},'p',test))}`
     )
   })
 
@@ -151,9 +151,15 @@ describe('codegen', () => {
   })
 
   it('generate DOM props with v-bind directive', () => {
+    // input + value
+    assertCodegen(
+      '<input :value="msg">',
+      `with(this){return _h('input',{domProps:{"value":msg}})}`
+    )
+    // non input
     assertCodegen(
       '<p :value="msg">',
-      `with(this){return _h('p',{domProps:{"value":msg}})}`
+      `with(this){return _h('p',{attrs:{"value":msg}})}`
     )
   })