研究過程
創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供弓長嶺網(wǎng)站建設(shè)、弓長嶺做網(wǎng)站、弓長嶺網(wǎng)站設(shè)計、弓長嶺網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、弓長嶺企業(yè)網(wǎng)站模板建站服務(wù),十多年弓長嶺做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。
一般形式
data:{ n:0 } :以這樣的方式存儲數(shù)據(jù),vue能夠監(jiān)聽其變化嗎?顯然是不能的。
使用Obj.defineProperty
let data1 = {} Object.defineProperty(data1, 'n', { value: 0 })
為什么要使用defineProperty呢?這不是把一般形式復(fù)雜化了嗎?
引出主角getter setter。
如果我們想對數(shù)據(jù)監(jiān)聽進(jìn)行處理呢?(假設(shè)修改的數(shù)據(jù)必須>=0)
let data2 = {} data2._n = 0 Object.defineProperty(data2,'n',{ get(){ return this._n }, set(value){ if(value<0) return //在此處可以對數(shù)據(jù)的修改進(jìn)行操作 this._n = value } })
使用代理
如果對方直接修改data2._n怎么辦?我們讓data2變成匿名對象!
let data3 = proxy({ data:{n:0} }) //括號里是匿名對象,無法訪問 function proxy({data}){ const obj = {} Object.defineProperty(obj, 'n', { get(){ return data.n }, set(value){ if(value<0)return data.n = value } }) return obj // obj 就是代理 }
代理是什么?
如果用戶自己給匿名對象起了個名字怎么辦呢?
MyData = { n:0 } let data3 = proxy({ data:MyData }) MyData.n = -1 //成功賦值為-1
這種情況,我們也要進(jìn)行攔截處理。
//在4.中的proxy函數(shù)中加入這幾行 let value = data.n Object.defineProperty(data, 'n', { get(){ return value }, set(newValue){ if(newValue<0)return value = newValue } })
這樣,我們就對data進(jìn)行了監(jiān)聽。
data域的一個bug
new Vue({ data:{ obj:{ a:0 } }, template:`{{ obj.b }}`, methods:{ set(){ this.obj.b = 1 } } }) //bug:vue無法監(jiān)聽一開始data域中不存在的obj.b
解決方法:
data的初始化中加入b
data:{ obj:{ a:0, b:undefined //注意,vue中的null和undefined都不會被渲染出來 } }
使用Vue.set(this.obj,'b',1)
數(shù)組的長度又不固定,怎么提前聲明?
詳見vue文檔,變異方法 章節(jié)
總結(jié)
//看看下面的代碼,發(fā)現(xiàn)了什么? let data = proxy({ data:myData5 }) let vm = new Vue({ data: myData })
Vue正是使用了這種代理和監(jiān)聽的設(shè)計模式,形成的數(shù)據(jù)響應(yīng)式。
流程:聲明數(shù)據(jù) => 監(jiān)聽數(shù)據(jù) => 代理數(shù)據(jù) => 返回數(shù)據(jù)
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。