
1.3 Vue.js的响应式理解
Vue.js是一套响应式系统(Reactivity System)。许多前端框架(如Angular、React、Vue)都有自己的响应式引擎。对于Vue响应式,官方文档的解释是,当用户把一个普通的JavaScript对象传给Vue实例的data选项时,Vue.js将遍历此对象的所有属性,并使用Object.defineProperty把这些属性全部转换为getter/setter。简单来说,即在修改data属性之后,Vue.js会立刻监听,立刻渲染并更新页面。下面通过一个实例来具体理解Vue.js的响应式,代码如下。
<div id="app"> <div>Price :¥{{ price }}</div> <div>Total:¥{{ price * quantiy }}</div> <div>Taxes: ¥{{ totalPriceWithTax }}</div> <button @click="changePrice">改变价格</button> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data() { return { price: 5.0, quantiy: 2 }; }, computed: { totalPriceWithTax() { return this.price * this.quantity * 1.03; } }, methods: { changePrice() { this.price = 10; } } }) </script>
价格改变前后的浏览器页面渲染效果如图1-5和图1-6所示。
在以上实例中,当数据price发生变化的时候,Vue.js就会自动做3件事情:更新页面中price的值;计算表达式price*quantity的值,更新页面;调用totalPriceWithTax函数,更新页面。数据发生变化后,会重新对页面进行渲染,这就是Vue响应式。那么,这一切是怎么做到的呢?想完成这个过程,就需要侦测数据的变化,在收集视图依赖于哪些数据和数据变化时,自动“通知”需要更新的视图部分并进行更新,即所谓的数据劫持/数据代理、依赖收集和发布订阅模式。其中,最核心的方法便是通过Object.defineProperty()来实现对属性的监听,达到监听数据变动的目的。要实现MVVM的数据双向绑定,就必须实现以下几点。

图1-5 价格改变前的浏览器页面渲染效果

图1-6 价格改变后的浏览器页面渲染效果
(1)实现一个数据监听器(Observer),能够对数据对象的所有属性进行监听,如有变动可取得最新值并通知订阅者。
(2)实现一个指令解析器(Compile),对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数。
(3)实现一个订阅者(Watcher),作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图。Vue响应式实现原理如图1-7所示。

图1-7 Vue响应式实现原理