Browse Source

support class/style in v-bind object

Evan You 9 years ago
parent
commit
59b2a0eeb3
3 changed files with 35 additions and 4 deletions
  1. 1 0
      flow/vnode.js
  2. 8 4
      src/core/instance/render.js
  3. 26 0
      test/unit/features/directives/bind.spec.js

+ 1 - 0
flow/vnode.js

@@ -53,6 +53,7 @@ declare interface VNodeData {
   };
   directives?: Array<VNodeDirective>;
   keepAlive?: boolean;
+  [key: string]: any;
 }
 
 declare type VNodeDirective = {

+ 8 - 4
src/core/instance/render.js

@@ -165,10 +165,14 @@ export function renderMixin (Vue: Class<Component>) {
         }
         const data = vnode.data
         for (const key in value) {
-          const hash = asProp || config.mustUseProp(key)
-            ? data.domProps || (data.domProps = {})
-            : data.attrs || (data.attrs = {})
-          hash[key] = value[key]
+          if (key === 'class' || key === 'style') {
+            data[key] = value[key]
+          } else {
+            const hash = asProp || config.mustUseProp(key)
+              ? data.domProps || (data.domProps = {})
+              : data.attrs || (data.attrs = {})
+            hash[key] = value[key]
+          }
         }
       }
     }

+ 26 - 0
test/unit/features/directives/bind.spec.js

@@ -144,6 +144,32 @@ describe('Directive v-bind', () => {
     }).then(done)
   })
 
+  it('bind object with class/style', done => {
+    const vm = new Vue({
+      template: '<input class="a" style="color:red" v-bind="test">',
+      data: {
+        test: {
+          id: 'test',
+          class: ['b', 'c'],
+          style: { fontSize: '12px' }
+        }
+      }
+    }).$mount()
+    expect(vm.$el.id).toBe('test')
+    expect(vm.$el.className).toBe('a b c')
+    expect(vm.$el.style.color).toBe('red')
+    expect(vm.$el.style.fontSize).toBe('12px')
+    vm.test.id = 'hi'
+    vm.test.class = ['d']
+    vm.test.style = { fontSize: '14px' }
+    waitForUpdate(() => {
+      expect(vm.$el.id).toBe('hi')
+      expect(vm.$el.className).toBe('a d')
+      expect(vm.$el.style.color).toBe('red')
+      expect(vm.$el.style.fontSize).toBe('14px')
+    }).then(done)
+  })
+
   it('bind object as prop', done => {
     const vm = new Vue({
       template: '<input v-bind.prop="test">',