這篇文章主要講解了如何實(shí)現(xiàn)Vue Object的變化偵測,內(nèi)容清晰明了,對此有興趣的小伙伴可以學(xué)習(xí)一下,相信大家閱讀完之后會有幫助。
創(chuàng)新互聯(lián)公司專注于企業(yè)成都全網(wǎng)營銷、網(wǎng)站重做改版、柳江網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、html5、商城網(wǎng)站開發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)公司、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為柳江等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
數(shù)據(jù)觀察
Vue 中的對象變化偵測是通過Object.definePorperty實(shí)現(xiàn)的,但是Object.definePorperty的方式有缺陷,比如不能直接代理整個對象,每次都要循環(huán)遍歷對象的所有屬性;尤大大說之后會使用 ES6 中的Proxy 重寫這個部分。這篇博客介紹的是 Object.definePorperty 實(shí)現(xiàn)的對象偵測。
我們來看下面這段代碼,定義一個 defineReactive 函數(shù),使用 Object.definePorperty 遍歷對象對象屬性的時候,設(shè)置 get 和 set;當(dāng)對象屬性被讀取的時候觸發(fā) get,對象屬性被設(shè)置的時候觸發(fā) set。這樣就完成了對 data 的數(shù)據(jù)劫持,因為 Vue 的思想是響應(yīng)式的,我們還需要收集這些變化。
function defineReactive(data,key,val){ Object.definePorperty(data,key,{ enumerable: true, configurable: true, get:function(){ return val; } set :function (newVal){ if(val === newVal){return} val = newVal; } }) }
依賴 收集
創(chuàng)建一個 Dep 類,在 get 中收集依賴,在 set 中新增依賴
class Dep{ constructor(){ this.arr = [] } addSub(sub){ this.arr.push(sub) } removeSub(sub){ remove(this.arr,sub) } depend(){ if(window.target){ this.addSub(window.target) } } notify(){ const arrs = this.arr.slice(); for(let i = 0; i< arrs.lenth ;i ++){ arrs[i].update(); } } } function defineReactive(data,key,val){ let dep = new Dep() Object.definePorperty(data,key,{ enumerable: true, configurable: true, get:function(){ dep.depend(); // 收集依賴 return val; } set :function (newVal){ if(val === newVal){return} val = newVal; dep.notify(); // 新增依賴 } }) }
Observer 和 Watcher
我們發(fā)現(xiàn) defineReactive 函數(shù)只能將某一個屬性轉(zhuǎn)換為 get/set 的形式,所以我們需要一個觀察者 Observer 用來幫助遞歸的偵測所有的 key
class Observer{ constructor(value){ this.value = value } if(!Array.isArry(value)){ this.walk(value) } walk(obj){ const keys = Object.keys(obj) for(let i = 0; i < keys.length ;i++){ defineReactive(data,keys[i],obj[keys[i]) } } }
當(dāng)這些依賴收集完成之后,我們要通知誰呢?怎么樣能讓視圖知道有變化更新?我們需要實(shí)現(xiàn)一個訂閱者 Watcher,
每次觸發(fā) get 的時候都將 dep 指向自己,這樣就可以收集到依賴;
每次 set 的時候都循環(huán)調(diào)用 Watcher 的 update 方法。
class Watcher{ constructor(vm,exp,cb){ this.vm = vm; this.cb = cb; this.exp = exp; this.value = this.get(); } get(){ Dep.target = this; // 將當(dāng)前訂閱者指向自己 var value = this.vm[exp]; // 觸發(fā)getter,添加自己到屬性訂閱器中 Dep.target = null; // 添加完畢,重置 return value; } update(){ const oldVal = this.value; this.value = this.get(); this.cb.call(this.vm,this.value,oldVal) } }
當(dāng) Vue 實(shí)例掛載好之后,模板都會綁定一個 Watcher,誰的屬性發(fā)生變化了就會通知響應(yīng)的 Watcher,Watcher 再去通知編譯器 Compile 進(jìn)行視圖更新
偵測沒辦法監(jiān)聽到對象上屬性的新增和刪除
Vue 通過Object.definePorperty將對象的 key 轉(zhuǎn)化為 getter setter 的形式來進(jìn)行偵測,但是無法追蹤到屬性的新增和刪除,所以 Vue 中提供了 vm.get 來實(shí)現(xiàn)
看完上述內(nèi)容,是不是對如何實(shí)現(xiàn)Vue Object的變化偵測有進(jìn)一步的了解,如果還想學(xué)習(xí)更多內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
文章名稱:如何實(shí)現(xiàn)VueObject的變化偵測
路徑分享:http://chinadenli.net/article38/ppgpsp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、商城網(wǎng)站、網(wǎng)站設(shè)計、關(guān)鍵詞優(yōu)化、網(wǎng)站排名、建站公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)