vue计算属性特别好用,可是它是如何作到的这一点的呢?vue
咱们首先从一个案例开始。它有一个input能够输入货币值,另一个span会把货币加上一¥符号。当货币值变化时,span会跟着变化:git
<script src="https://unpkg.com/vue/dist/vue.js"></script> <div id="app"> <input v-model="money"></input> <span>{{RMB}}</span> </div> <script> new Vue({ el:'#app', data:{ money:1.10 }, computed:{ RMB:function(){ return '¥'+this.money } } }) </script>
这里的RMB属性就是一个计算属性,依赖于this.money,伴随后者的变化而变化。bootstrap
然而,这是如何作到的?难道vuejs分析了rmb函数内的表达式吗。要知道这一点,咱们得了解响应式属性的概念和技术。经过DefineProperty,能够建立一个看起来是普通数据,可是背后还有getter/setter函数的属性,像是这样:app
var bank = {moneyNormal:1}; Object.defineProperty (bank, 'money', { get: function () { console.log ("Getting money"); return 1; } }); console.log ("money:", bank.money,bank.moneyNormal);
尽管使用起来bank.money和bank.moneyNormal差很少,实际上每次访问money会首先通过getter函数,这样就能够在此函数内作些本身想要作的事儿。vue就是会把全部在data返回的属性作一次DefineProperty处理,把它变成响应式的属性,所以每次访问此类属性,vue均可以知道的。这一点对于计算属性相当重要!函数
再进一步,就是当RMB计算属性被调用执行时,必然会调用到this.money,this.money会引起它本身的getter函数。所以只要在RMB属性调用this.money以前作些手脚,让this.money的getter知道此调用是从RMB getter来的便可记录以来,将来改变this.money,就能够通知依赖,由此引起连锁的更新反应。代码:this
var Dep = { target: null } function defineVUEProperty (obj, key, val) { var deps = []; Object.defineProperty (obj, key, { get: function () { // 处理计算依赖 if (Dep.target && deps.indexOf (Dep.target) == -1) { deps.push (Dep.target); } return val; }, set: function (newValue) { val = newValue; // 处理计算依赖 for (var i = 0; i < deps.length; i ++) { deps[i](); } } }) } function defineVUEComputed (obj, key, computeFunc) { var onDependencyUpdated = function () { var value = computeFunc (); console.log('dependence value:'+value) }; Object.defineProperty (obj, key, { get: function () { // 处理计算依赖 Dep.target = onDependencyUpdated; var value = computeFunc (); // 处理计算依赖 Dep.target = null; return value; } }) } //demo code var bank = {}; defineVUEProperty (bank, 'money', 1); defineVUEComputed (bank, 'RMB', function () { return '$'+bank.money }); console.log (bank.money,bank.RMB) bank.money = 22;
咱们会发现,当执行完代码bank.money = 22;
,确实会激发RMB的重算,由于代码打印了:spa
dependence value:¥42
作出手脚的代码已经被标注出来。要点是code
首先由一个全局变量Dep,它是一个单实例对象,成员为target。orm
当执行计算属性的getter时,它设置一个回调函数到Dep.target,而后调用被依赖的属性的getter,在此getter内检查Dep.target,若是有值而且没有加入当前属性的依赖列表就把它加进来。这样就把依赖此属性的计算属性指定的回调加入了依赖列表内。对象
修改属性(调用属性的setter)时,对应的setter函数调用全部前一步加入的依赖列表内的回调,等因而把控制权转移给了对应的计算属性
改编于:Vue.js Internals: How computed properties work | Anirudh Sanjeev
做者:刘传君
建立过产品,创过业。好读书,求甚解。
能够经过 1000copy#gmail.com 联系到我
bootstrap小书 https://www.gitbook.com/book/...
http小书 http://www.ituring.com.cn/boo...
Git小书 http://www.ituring.com.cn/boo...