Vue data的數(shù)據(jù)響應(yīng)式到底是如何實(shí)現(xiàn)的
研究過程
一般形式
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 就是代理
}
代理是什么?
- 對data的屬性的讀寫,全權(quán)交給另一個對象obj負(fù)責(zé),那么obj就是data的代理
- data.n不使用,偏要使用obj.n來操作data.n
如果用戶自己給匿名對象起了個名字怎么辦呢?
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:`
<div @click="set">{{ obj.b }}</div>
`,
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.set (不推薦)
- 使用this.array.push (被Vue改寫過的push,實(shí)現(xiàn)了代理和監(jiān)聽)
詳見vue文檔,變異方法 章節(jié)
總結(jié)
//看看下面的代碼,發(fā)現(xiàn)了什么?
let data = proxy({ data:myData5 })
let vm = new Vue({ data: myData })
Vue正是使用了這種代理和監(jiān)聽的設(shè)計(jì)模式,形成的數(shù)據(jù)響應(yīng)式。
流程:聲明數(shù)據(jù) => 監(jiān)聽數(shù)據(jù) => 代理數(shù)據(jù) => 返回?cái)?shù)據(jù)
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue.js打包項(xiàng)目后頁面出現(xiàn)空白的解決辦法
這篇文章主要介紹了vue.js打包項(xiàng)目后頁面出現(xiàn)空白的解決辦法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2021-11-11
vscode中eslint插件的配置(prettier配置無效)
這篇文章主要介紹了vscode中eslint插件的配置(prettier配置無效),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
當(dāng)啟動vue項(xiàng)目安裝依賴時報錯的解決方案
這篇文章主要介紹了當(dāng)啟動vue項(xiàng)目安裝依賴時報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04
解決el-upload批量上傳只執(zhí)行一次成功回調(diào)on-success的問題
這篇文章主要介紹了解決el-upload批量上傳只執(zhí)行一次成功回調(diào)on-success的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
Vue過渡效果之CSS過渡詳解(結(jié)合transition,animation,animate.css)
Vue 在插入、更新或者移除 DOM 時,提供多種不同方式的應(yīng)用過渡效果。本文將從CSS過渡transition、CSS動畫animation及配合使用第三方CSS動畫庫(如animate.css)這三方面來詳細(xì)介紹Vue過渡效果之CSS過渡2020-02-02

