理解vue数据驱动 (3)

为什么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里更合适。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyxyzg.html