为什么this.next明明赋值,没有渲染到view中去?因为他并没有参与数据驱动的观察者,还记得前面讲到vue会把传入的data对象深度遍历包装为观察者来吧,这里next属性并没有被成为观察者,因此并不会引发view更新。
看到的未必真实的为什么看到的未必真实的,上面的栗子我们发现,view中看到的只有hello,但是数据真的是有hello么?未必,看下面栗子。
new Vue({ el: "#app", data: { prev: 'hello', }, created() { }, mounted() { this.next = 'world'; setTimeout(() => { this.prev = 'hi'; }, 1000); } })这个代码比上面栗子就多了3行代码,再页面渲染1秒后,改变prev的值为hi,那么页面会展现什么效果呢?
答:hi world
从这里可以看到,虽然next赋值并没有引起view更新,但是data确实成功变更了,当prev改变时,触发了update,从而将view更新,此时next有值,因此就显示在了view中。这就是很多初学者会遇到为什么明明赋值没有显示,但是点了一下其他的东西,却显示了的问题。
看到的未必真实2还是根据第一个栗子引申一个案例如下:
new Vue({ el: "#app", data: { prev: 'hello', }, created() { this.next = 'world'; }, mounted() { setTimeout(() => { this.next = 'memory' }, 1000) } })我们在created生命周期中赋值next,在mounted生命周期延迟一秒改变next的值,那结果会这样?
答:永远显示helloworld
如果已经掌握了vue实例化过程的同学可能已经猜到了为什么
当created生命周期执行时,此时还没有做vnode转化为真实dom的操作,此时data属性已经代理到this下,因此修改this.next就修改了data对象的值,data就变为了{prev: 'hello', next: 'world'},因此在render时就将next也渲染到了页面上
另外此时已经完成了数据驱动的灵魂步骤(将data遍历包装为观察者),因此在延迟1s后改变next值,仍然跟栗子2一样不会引起view更新的。
因此,写vue出现以上改变data时view未更新,首先要检查自己的代码,而不是怀疑vue框架的问题。。
注意事项本文参考vue版本v2.5.17-beta.0
本文专注数据驱动主线data,computed等支线并没有介绍,因此贴的代码都做了大量删减
data属性收集到的依赖Dep.target并不止updateComponent的Watcher,还可能多个,比如computed属性
附加讨论有些面试官会问在异步获取数据并改变data值时,放在created还是mounted?
我感觉没什么可答的,2个都没问题,当然对于代码优化,放在created更早的发出请求,因此放在created里更合适。