Vue data的數(shù)據(jù)響應(yīng)式到底是如何實(shí)現(xiàn)的
研究過(guò)程
一般形式
data:{ n:0 } :以這樣的方式存儲(chǔ)數(shù)據(jù),vue能夠監(jiān)聽(tīng)其變化嗎?顯然是不能的。
使用Obj.defineProperty
let data1 = {} Object.defineProperty(data1, 'n', { value: 0 })
為什么要使用defineProperty呢?這不是把一般形式復(fù)雜化了嗎?
引出主角getter setter。
如果我們想對(duì)數(shù)據(jù)監(jiān)聽(tīng)進(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 //在此處可以對(duì)數(shù)據(jù)的修改進(jìn)行操作 this._n = value } })
使用代理
如果對(duì)方直接修改data2._n怎么辦?我們讓data2變成匿名對(duì)象!
let data3 = proxy({ data:{n:0} }) //括號(hào)里是匿名對(duì)象,無(wú)法訪問(wèn) 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 就是代理 }
代理是什么?
- 對(duì)data的屬性的讀寫,全權(quán)交給另一個(gè)對(duì)象obj負(fù)責(zé),那么obj就是data的代理
- data.n不使用,偏要使用obj.n來(lái)操作data.n
如果用戶自己給匿名對(duì)象起了個(gè)名字怎么辦呢?
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 } })
這樣,我們就對(duì)data進(jìn)行了監(jiān)聽(tīng)。
data域的一個(gè)bug
new Vue({ data:{ obj:{ a:0 } }, template:` <div @click="set">{{ obj.b }}</div> `, methods:{ set(){ this.obj.b = 1 } } }) //bug:vue無(wú)法監(jiān)聽(tīng)一開(kāi)始data域中不存在的obj.b
解決方法:
data的初始化中加入b
data:{ obj:{ a:0, b:undefined //注意,vue中的null和undefined都不會(huì)被渲染出來(lái) } }
使用Vue.set(this.obj,'b',1)
數(shù)組的長(zhǎng)度又不固定,怎么提前聲明?
- 使用Vue.set (不推薦)
- 使用this.array.push (被Vue改寫過(guò)的push,實(shí)現(xiàn)了代理和監(jiān)聽(tīng))
詳見(jiàn)vue文檔,變異方法 章節(jié)
總結(jié)
//看看下面的代碼,發(fā)現(xiàn)了什么? let data = proxy({ data:myData5 }) let vm = new Vue({ data: myData })
Vue正是使用了這種代理和監(jiān)聽(tīng)的設(shè)計(jì)模式,形成的數(shù)據(jù)響應(yīng)式。
流程:聲明數(shù)據(jù) => 監(jiān)聽(tīng)數(shù)據(jù) => 代理數(shù)據(jù) => 返回?cái)?shù)據(jù)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue?element修改el-select控件長(zhǎng)度style=“width:XXpx“不生效的解決
這篇文章主要介紹了vue?element修改el-select控件長(zhǎng)度style=“width:XXpx“不生效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07vue實(shí)現(xiàn)的樹(shù)形結(jié)構(gòu)加多選框示例
這篇文章主要介紹了vue實(shí)現(xiàn)的樹(shù)形結(jié)構(gòu)加多選框,結(jié)合實(shí)例形式分析了在之前遞歸組件實(shí)現(xiàn)vue樹(shù)形結(jié)構(gòu)的基礎(chǔ)之上再加上多選框功能相關(guān)操作技巧,需要的朋友可以參考下2019-02-02Vue實(shí)現(xiàn)點(diǎn)擊圖片放大顯示功能
這篇文章主要為大家詳細(xì)介紹了如何利用Vue實(shí)現(xiàn)點(diǎn)擊圖片放大顯示功能,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,感興趣的可以了解一下2023-03-03Vue點(diǎn)擊在彈窗外部實(shí)現(xiàn)一鍵關(guān)閉的示例代碼
在Vue應(yīng)用中,彈窗是一個(gè)常見(jiàn)的交互元素,有時(shí)我們可能希望用戶點(diǎn)擊彈窗外部時(shí),彈窗能夠自動(dòng)關(guān)閉,本文主要介紹了Vue點(diǎn)擊在彈窗外部實(shí)現(xiàn)一鍵關(guān)閉的示例代碼,感興趣的可以了解一下2024-06-06vue3?父控件遠(yuǎn)程獲取數(shù)據(jù)在子組件上顯示不出來(lái)的解決方案
這篇文章主要介紹了vue3?父控件遠(yuǎn)程獲取數(shù)據(jù),在子組件上顯示不出來(lái),本文給大家分享兩種解決方案幫助大家解決這個(gè)問(wèn)題,需要的朋友可以參考下2023-08-08vue2.0實(shí)現(xiàn)倒計(jì)時(shí)的插件(時(shí)間戳 刷新 跳轉(zhuǎn) 都不影響)
我發(fā)現(xiàn)好多倒計(jì)時(shí)的插件,刷新都會(huì)變成從頭再來(lái),于是自己用vue2.0寫了一個(gè),感覺(jué)還不錯(cuò),特此分享到腳本之家平臺(tái)供大家參考下2017-03-03Vue 數(shù)組和對(duì)象更新,但是頁(yè)面沒(méi)有刷新的解決方式
今天小編就為大家分享一篇Vue 數(shù)組和對(duì)象更新,但是頁(yè)面沒(méi)有刷新的解決方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11