新聞中心
Vue.js的核心包括一套“響應(yīng)式系統(tǒng)”?!绊憫?yīng)式”,是指當(dāng)數(shù)據(jù)改變后,Vue會(huì)通知到使用該數(shù)據(jù)的代碼。例如,視圖渲染中使用了數(shù)據(jù),數(shù)據(jù)改變后,視圖也會(huì)自動(dòng)更新。

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長期合作伙伴,公司提供的服務(wù)項(xiàng)目有:空間域名、網(wǎng)頁空間、營銷軟件、網(wǎng)站建設(shè)、同江網(wǎng)站維護(hù)、網(wǎng)站推廣。
1. ES語法的getter和setter
在開始了解 Vue 的數(shù)據(jù)響應(yīng)式原理前應(yīng)該先搞清楚 ES語法 中的 getter 和 setter 方法的具體用法。
getter和setter 方法是以 get 和 set 關(guān)鍵字來為對象添加虛擬屬性的一種方式。這種屬性其實(shí)并不真實(shí)存在,而是以取值函數(shù) getter 和存值函數(shù) setter 來模擬的一種屬性。目的是對某個(gè)屬性設(shè)置存值函數(shù)和取值函數(shù),攔截該屬性的存取行為,以便于對該屬性的存取做一些限定處理。如下所示(以下代碼來源于 mdn)
getter 方法
const obj = {
log: ['a', 'b', 'c'],
get latest() { //在正常方法前加 get 關(guān)鍵字
if (this.log.length == 0) {
return undefined;
}
return this.log[this.log.length - 1];
}
}
console.log(obj.latest);// 輸出 c,獲取的是屬性名不用帶括號
setter方法
const language = {
set current(name) {
this.log.push(name);
},
log: []
}
language.current = 'EN';
language.current = 'FA';
console.log(language.log);//輸出 Array ["EN", "FA"]
2. ES語法的 defineProperty
defineProperty 方法會(huì)直接在一個(gè)對象上定義一個(gè)新屬性,或者修改一個(gè)對象的現(xiàn)有屬性, 并返回這個(gè)對象,可用于在一個(gè)對象定義好后為其修改或添加屬性。 語法為:
Object.defineProperty(obj, prop, descriptor)
添加常規(guī)屬性:
let data = {
m: 0
}
Object.defineProperty(data, 'n', {
value: 1 //添加屬性的 value 就是其值
})
console.log(`${data.n}`) //則會(huì)輸出n值為1
也可用來添加 getter 和 setter 的虛擬屬性
let data1 = {
_n: 0
}
Object.defineProperty(data1, 'n', {
get(){
return this._n
},
set(value){
if(value return
this._n = value
}//直接寫明 get / set 即可
}) //由于指明了虛擬屬性為 n,即 get n(){}、set n(value){},因此在函數(shù)定義時(shí)就不用再寫n了
3. Vue對數(shù)據(jù)的代理和監(jiān)聽
代理,即 proxy,簡單來說我自己的一些事情我自己不親自處理,而是交給一個(gè)人讓他去幫我做,那個(gè)做事的人就是代理。這個(gè)邏輯中有兩個(gè)關(guān)鍵點(diǎn)需要搞清楚,代理是處理操作的人,而其處理操作的事情不屬于他,而是屬于委托其代理的人的。
因此類比到 Vue數(shù)據(jù)代理 ,委托代理的是 data{} 數(shù)據(jù)對象,其找到代理就是 Vue實(shí)例vm ,data{} 數(shù)據(jù)對象要代理 vm 做的事情是管理 data{} 數(shù)據(jù)對象里數(shù)據(jù)操作。因此 data{} 數(shù)據(jù)對象只負(fù)責(zé)內(nèi)部數(shù)據(jù)的生產(chǎn)即可,對生產(chǎn)出來的數(shù)據(jù)的管理和操作全權(quán)交給 vm 處理。
那么 vm 如何對 data{} 數(shù)據(jù)對象里的數(shù)據(jù)進(jìn)行控制和操作呢?換句話說,vm 如何在 data{} 數(shù)據(jù)對象里面的任意一個(gè)屬性值變化時(shí)都及時(shí)知道呢?
于是便用到了 ES 語法中的 getter和setter 方法,通過 getter和setter 方法控制的屬性的任何操作都會(huì)被這兩個(gè)函數(shù)檢測到,而 getter和setter 方法形成的屬性是虛擬屬性,真實(shí)并不存在,因此如果用戶想私自不經(jīng)過代理 vm 直接修改 data{} 數(shù)據(jù)對象的屬性也獲取不到對應(yīng)的實(shí)體屬性,只能通過 getter和setter 方法修改,那么其修改就必定被 vm 檢測到。
因此 vm 為了實(shí)現(xiàn)對 data{} 數(shù)據(jù)對象里數(shù)據(jù)的全部控制,就必須在 Vue實(shí)例 創(chuàng)建的時(shí)候?qū)鬟M(jìn)來的 data{} 數(shù)據(jù)對象做一些處理,做的處理就是將 data{} 數(shù)據(jù)對象里的屬性都變成了 getter和setter 方法控制的虛擬屬性,并保存在代理數(shù)據(jù)對象 obj 并返回。
但為了不讓用戶直接修改原來的 data{} 屬性,也將原來的 data{} 對象的實(shí)體屬性全改變了,添加的虛擬屬性名字和實(shí)體屬性名一樣,就會(huì)用虛擬屬性覆蓋原來的實(shí)際屬性,用戶在修改屬性值是就是通過 getter和setter 方法修改的虛擬屬性。這樣一來 data{} 數(shù)據(jù)對象的全部屬性的任何變化都會(huì)被 Vue實(shí)例vm 檢測到。
let myData = {n:0}
let data = proxy({ data:myData }) // 類似于 let vm = new Vue({data: myData})
function proxy({data}/* 解構(gòu)賦值*/){
let _n = data.n
Object.defineProperty(data, 'n', { //覆蓋原來的data.n屬性
get(){
return _n
},
set(newValue){
if(newValuereturn
_n = newValue
}
})// 改變data{}數(shù)據(jù)對象本身屬性,可通過閉包形成上下文,讓原來的實(shí)際屬性值存在閉包的上下文_n中
const obj = {}
Object.defineProperty(obj, 'n', {
get(){
return data.n
},
set(value){
data.n = value
}
}) //添加data{}數(shù)據(jù)對象的代理,對data{}數(shù)據(jù)對象操作
return obj // obj 就是data{}的代理
}
4. Vue的數(shù)據(jù)響應(yīng)式
所謂響應(yīng)式就是當(dāng)事物發(fā)生變化時(shí)會(huì)根據(jù)變化做出相應(yīng)的反映。
Vue 中的數(shù)據(jù) data 是響應(yīng)式的,由上述 Vue 通過 Object.defineProperty()函數(shù) 來用 getter和setter方法 對 data 數(shù)據(jù)做了代理和監(jiān)聽,一旦數(shù)據(jù)發(fā)生變化,Vue 就會(huì)改變數(shù)據(jù)對應(yīng)的 UI 視圖,這就是 Vue的數(shù)據(jù)響應(yīng)式
但是 Vue 使用 Object.defineProperty 來設(shè)置監(jiān)聽,就只能對在 Vue實(shí)例化 時(shí) data 對象里已經(jīng)存在的屬性設(shè)置監(jiān)聽,而對不存在的或者后來添加進(jìn)去的屬性沒有進(jìn)行監(jiān)聽。
為了解決這個(gè)問題,有兩種方法:
\1. 將所有屬性都提前聲明好
\2. 使用 Vue.set 和 this.$set 添加屬性
使用 Vue.set 和 this.$set 添加屬性是會(huì)通知 Vue 對這后添加的屬性也設(shè)置監(jiān)聽操作。
Vue.set('this.data','m','10')
this.$set('this.data','m','10')//為vm的data對象添加屬性m值為10
3.數(shù)組變異
對于數(shù)組的數(shù)據(jù)增加,無法控制其新增個(gè)數(shù)因此不能提前聲明所有數(shù)據(jù)值,而一個(gè)一個(gè) set 又太麻煩,而且數(shù)組是常用的對象數(shù)據(jù)類型中的一種,因此 vue 的作者就對數(shù)組的增刪函數(shù)如 push 和 pop 等進(jìn)行了篡改,用戶在使用 vue 中數(shù)組增刪時(shí)仍是用 push 和 pop ,但是里面進(jìn)行了額外的處理,這幾個(gè)被篡改的 API 會(huì)對數(shù)組新增是數(shù)據(jù)代理監(jiān)聽并根據(jù)數(shù)據(jù)響應(yīng)改變 UI 視圖。
以上就是深入理解Vue的數(shù)據(jù)響應(yīng)式的詳細(xì)內(nèi)容。
網(wǎng)頁標(biāo)題:Vue的數(shù)據(jù)響應(yīng)式詳解
標(biāo)題網(wǎng)址:http://fisionsoft.com.cn/article/cdddsoc.html


咨詢
建站咨詢
