浏览代码

include patch process in watcher getter to ensure correct dep collection for deep updates

Evan You 10 年之前
父节点
当前提交
54e648e49f

+ 4 - 3
src/core/instance/lifecycle.js

@@ -1,7 +1,7 @@
 /* @flow */
 
 import Watcher from '../observer/watcher'
-import { warn, validateProp, remove } from '../util/index'
+import { warn, validateProp, remove, noop } from '../util/index'
 import { observerState } from '../observer/index'
 import { updateListeners } from '../vdom/helpers'
 
@@ -44,8 +44,9 @@ export function lifecycleMixin (Vue: Class<Component>) {
       }
     }
     callHook(vm, 'beforeMount')
-    vm._watcher = new Watcher(vm, vm._render, vm._update)
-    vm._update(vm._watcher.value)
+    vm._watcher = new Watcher(vm, () => {
+      vm._update(vm._render())
+    }, noop)
     vm._isMounted = true
     // root instance, call mounted on self
     if (vm.$root === vm) {

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

@@ -2,8 +2,8 @@
 
 import VNode, { emptyVNode } from '../vdom/vnode'
 import { normalizeChildren } from '../vdom/helpers'
-import { bind, remove, isObject, renderString } from 'shared/util'
 import { resolveAsset, nextTick } from '../util/index'
+import { bind, remove, extend, isObject, renderString } from 'shared/util'
 
 import {
   renderElement,

+ 1 - 1
src/platforms/web/compiler/modules/style.js

@@ -13,7 +13,7 @@ function parse (el: ASTElement) {
 
 function genData (el: ASTElement): string {
   return el.styleBinding
-    ? `style:${el.styleBinding},`
+    ? `style:(${el.styleBinding}),`
     : ''
 }
 

+ 4 - 1
src/platforms/web/runtime/modules/style.js

@@ -1,6 +1,6 @@
 /* @flow */
 
-import { cached, camelize, toObject } from 'shared/util'
+import { cached, camelize, toObject, extend } from 'shared/util'
 
 const prefixes = ['Webkit', 'Moz', 'ms']
 
@@ -45,6 +45,9 @@ function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
       elm.style[normalize(name)] = cur
     }
   }
+  // clone the style for future updates,
+  // in case the user mutates the style object in-place.
+  vnode.data.style = extend({}, style)
 }
 
 export default {

+ 14 - 0
test/unit/features/directives/class.spec.js

@@ -92,4 +92,18 @@ describe('Directive v-bind:class', () => {
       expect(vm.$el.className).toBe('c a bar baz foo')
     }).then(done)
   })
+
+  it('deep update', done => {
+    const vm = new Vue({
+      template: '<div :class="test"></div>',
+      data: {
+        test: { a: true, b: false }
+      }
+    }).$mount()
+    expect(vm.$el.className).toBe('a')
+    vm.test.b = true
+    waitForUpdate(() => {
+      expect(vm.$el.className).toBe('a b')
+    }).then(done)
+  })
 })

+ 2 - 11
test/unit/features/directives/style.spec.js

@@ -116,19 +116,10 @@ describe('Directive v-bind:style', () => {
   })
 
   it('updates objects deeply', done => {
-    const el = document.createElement('div')
-    el.setAttribute(':style', 'divStyling')
-    vm = new Vue({
-      el,
-      data () {
-        return {
-          divStyling: { display: 'none' }
-        }
-      }
-    })
+    vm.styles = { display: 'none' }
     waitForUpdate(() => {
       expect(vm.$el.style.display).toBe('none')
-      vm.divStyling = extend({}, { display: 'block' })
+      vm.styles.display = 'block'
     }).then(() => {
       expect(vm.$el.style.display).toBe('block')
     }).then(done)

+ 1 - 1
test/unit/modules/compiler/codegen.spec.js

@@ -156,7 +156,7 @@ describe('codegen', () => {
   it('generate style binding', () => {
     assertCodegen(
       '<p :style="error">hello world</p>',
-      `with(this){return _h(_e('p',{style:error}),[_t("hello world")])}`
+      `with(this){return _h(_e('p',{style:(error)}),[_t("hello world")])}`
     )
   })