面试问题:Vuejs如何实现双向绑定

最近出去面试,栽在这个问题上,提到vuejs,面试官通常会让你说vuejs的特色,通常就要回答virtual dom tree, dom tree diff, 以及数据双向绑定,而后面试官会追问你,vuejs是如何实现数据双向绑定的,前面的问题算基础的话,能答出这个就更上一个台阶,说明你的思考能力不停留在表层,遗憾的是我只能大概说出Object.defineProperty。
我回来搜了一下,发现其实vuejs的官网对这个原理是有详尽的阐释的,若是失败了只能怪本身准备不足。这篇文章我就整理一下分享给你们,若是有错误还请指出。html

vuejs官网对这个问题的解释是 对响应式原理的解释,这里:https://cn.vuejs.org/v2/guide...vue

问题就是vuejs如何追踪对象的属性变化,答是利用es5的Object.defineProperty,参考:https://developer.mozilla.org...react

Object.defineProperty是一个没法被shim的属性,就是说它没法被降级使用,这也是vuejs不支持ie8如下的根本缘由。面试

Object.defineProperty用来设置一个对象的某一个属性,这都不是最关键的,关键是在设置属性的同时,能够设置setter/getter,setter/getter设置两个函数,在这个属性被调用或者设置的时候自动执行,因此在setter的函数里,只要写了更新dom的方法,就能够在这个属性变化的时候执行,实现了属性变化的追踪。dom

实际上,vuejs的实现更加复杂,遵守这张流程图:
data.pngide

vuejs里每个组件对应了一个watcher,Object.defineProperty是紫色的圆圈,当组件里某一个属性被get的时候,getter函数会通知Watcher,“说我这有一个属性被渲染了,你记一下”,而后当这个属性的setter被触发(也就是该属性数据被修改的时候),也会通知Watcher,说“我这有这样一个东西被改了,你看看在不在你的名单里。”Watcher此时去检查被改的属性在不在本身记录的名单里,若是在,就通知组件渲染程序,让它再去更新虚拟dom树。函数

须要注意的几个点:

1.getter/setter对用户是不可见的,是在vue内部实现的。
2.js里没法监听对象属性的增长或者删除,因此vue只能在开始data里添加响应式属性,因此当组件建立完毕,再给这个组件塞一个属性,这个属性是没法响应到dom的。
3.vue会在组件初始化的过程当中进行getter/setter转换,因此也没法动态插入新属性,插入了也是非响应数据,但能够经过Vue.set(object, key, value)方法将属性加入到后台可响应的对象中。
4.官网还介绍了更新队列,上文说的Watcher中的更新会被推入到一个更新队列中,那么就是说数据更新后不会立刻反映到dom上。
5.可是咱们能够经过Vue.nextTick(callback)方法,将此次数据更新立刻反映到dom上,这个方法的callback是dom更新完成的回调。ui

相关文章
相关标签/搜索