Vue深入講解數(shù)據(jù)響應(yīng)式原理
響應(yīng)式是什么
簡而言之就是數(shù)據(jù)變頁面變
如何實現(xiàn)數(shù)據(jù)響應(yīng)式
在Javascript里實現(xiàn)數(shù)據(jù)響應(yīng)式一般有倆種方案,分別對應(yīng)著vue2.x 和 vue3.x使用的方式,他們分別是:
對象屬性攔截 (vue2.x)
Object.defineProperty
對象整體代理 (vue3.x)
Proxy
其中對象屬性攔截,道理都是相通的
實現(xiàn)對象屬性攔截
字面量對象定義
let data = {
name:'小蘭同學(xué)'
}
Object.defineProperty對象定義
let data = {}
Object.defineProperty(data,'name',{
// 訪問name屬性就會執(zhí)行此方法 返回值就是獲取到的值
get(){
console.log('name屬性被獲取了')
return '小蘭同學(xué)'
},
// 設(shè)置新值就會執(zhí)行此方法 newVal就是設(shè)置的新值
set(newVal){
console.log('name屬性被設(shè)置新值了')
console.log(newVal)
}
})
我們可以通過 data.name 去獲取值,也可以通過 data.name=‘小趙同學(xué)’去賦值
存在問題演示
最后獲取name值沒有被改變

解決方案
我們可以 通過一個中間變量 _name 來中轉(zhuǎn)get函數(shù)和set函數(shù)之間的聯(lián)動
let data = {}
let _name = '小蘭同學(xué)'
Object.defineProperty(data,'name',{
// 訪問name屬性就會執(zhí)行此方法 返回值就是獲取到的值
get(){
console.log('name屬性被獲取了')
return _name
},
// 設(shè)置新值就會執(zhí)行此方法 newVal就是設(shè)置的新值
set(newVal){
console.log('name屬性被設(shè)置新值了')
console.log(newVal)
_name = newVal
}
})
結(jié)果驗證

通用的劫持方案
大家想想看,如果現(xiàn)在有一份已經(jīng)聲明好了數(shù)據(jù)的對象,我們?nèi)绾瓮ㄟ^劫持的方法把每一個屬性都變成setter和getter的形式
下面是一份已經(jīng)聲明好的數(shù)據(jù)
let data = {
name: '小蘭同學(xué)',
age: 18,
height:180
}
我們想讓里面所有的屬性都變成響應(yīng)式的,并且get和set方法中對于每個屬性值的操作是連通的
let data = {
name: '小蘭同學(xué)',
age: 18,
height:180
}
// 遍歷每一個屬性
Object.keys(data).forEach((key)=>{
// key 屬性名
// data[key] 屬性值
defineReactive(data,key,data[key])
})
// 響應(yīng)式轉(zhuǎn)化方法
function defineReactive(data,key,value){
Object.defineProperty(data,key,{
get(){
return value
},
set(newVal){
value = newVal
}
})
}
結(jié)構(gòu)說明:這個地方實際上使用了閉包的特性,看下圖,在每一次的defineReactive函數(shù)執(zhí)行的時候,都會形成一塊獨立的函數(shù)作用域,傳入的value 因為閉包的關(guān)系會常駐內(nèi)存,這樣一來,每個defineReactive函數(shù)中的value 會作為各自set和get函數(shù)操作的局部變量

總結(jié)
- 所謂的響應(yīng)式其實就是攔截對象屬性的訪問和設(shè)置,插入一些我們自己想要做的事情
- 在Javascript中能實現(xiàn)響應(yīng)式攔截的方法有倆種,
Object.defineProperty方法和Proxy對象代理 - 回歸到vue2.x中的data配置項,只要放到了data里的數(shù)據(jù),不管層級多深不管你最終會不會用到這個數(shù)據(jù)都會進行遞歸響應(yīng)式處理,所以要求我們?nèi)绶潜匾?,盡量不要添加太多的冗余數(shù)據(jù)在data中
- 需要了解vue3.x中,解決了2中對于數(shù)據(jù)響應(yīng)式處理的無端性能消耗,使用的手段是Proxy劫持對象整體 + 惰性處理(用到了才進行響應(yīng)式轉(zhuǎn)換)
到此這篇關(guān)于Vue深入講解數(shù)據(jù)響應(yīng)式原理的文章就介紹到這了,更多相關(guān)Vue數(shù)據(jù)響應(yīng)式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Electron中打包應(yīng)用程序及相關(guān)報錯問題的解決
這篇文章主要介紹了Electron中打包應(yīng)用程序及相關(guān)報錯問題的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
Vue/React子組件實例暴露方法(TypeScript)
最近幾個月都在用TS開發(fā)各種項目,框架有涉及到Vue3,React18等,記錄一下Vue/React組件暴露出變量/函數(shù)的方法的寫法,對vue?react組件暴露方法相關(guān)知識感興趣的朋友跟隨小編一起看看吧2022-11-11
vue查詢數(shù)據(jù)el-table不更新數(shù)據(jù)的解決方案
這篇文章主要介紹了vue查詢數(shù)據(jù)el-table不更新數(shù)據(jù)的問題及解決方案,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-12-12
使用vue官方提供的模板vue-cli搭建一個helloWorld案例分析
這篇文章主要介紹了用vue官方提供的模板vue-cli搭建一個helloWorld案例,需要的朋友可以參考下2018-01-01
vue踩坑記錄之echarts動態(tài)數(shù)據(jù)刷新問題
這篇文章主要介紹了vue踩坑記錄之echarts動態(tài)數(shù)據(jù)刷新問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
VueJs單頁應(yīng)用實現(xiàn)微信網(wǎng)頁授權(quán)及微信分享功能示例
本篇文章主要介紹了VueJs單頁應(yīng)用實現(xiàn)微信網(wǎng)頁授權(quán)及微信分享功能示例,具有一定的參考價值,有興趣的可以了解一下2017-07-07
vue服務(wù)器代理proxyTable配置如何解決跨域
這篇文章主要介紹了vue服務(wù)器代理proxyTable配置如何解決跨域問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04

