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...