前言
Vue 最獨特的特性之一凡怎,是其非侵入性的響應式系統(tǒng)协屡。數(shù)據(jù)模型僅僅是普通的 JavaScript 對象。而當你修改它們時茸俭,視圖會進行更新吊履。這使得狀態(tài)管理非常簡單直接,本文瓣履,我們將研究一下 Vue 響應式系統(tǒng)的一些原理
圖示
主要成員
在響應式原理中率翅,Observe、Dep袖迎、Watcher 這三個類是構(gòu)成完整原理的主要成員,Compile則是負責解析vue el
模板中引用的屬性
new Vue({
el:'#app',
data:{
name:"why",
age:18
}
})
<div id="app">
{{name}}
{{name}}
{{age}}
{{age}}
</div>
-
Observer監(jiān)聽劫持所有的vue
data
屬性
當你把一個普通的 JavaScript 對象傳入 Vue 實例作為data
選項冕臭,Vue 將遍歷此對象所有的 property腺晾,并使用Object.defineProperty
把這些 property 全部轉(zhuǎn)為 getter/setter。
每一個屬性就有一個Dep對象,Dep對象存放著所有watcher
name->Dep對象-subs[watcher1,watcher2]
age->Dep對象-subs[watcher1,watcher2]
-
Dep/Watcher
當我們改變data中屬性的值時,比如 name:'why' 改為 name:'cobe'時,會觸發(fā)Observer
對我們data屬性的監(jiān)聽,監(jiān)聽到name屬性
發(fā)生變化,會調(diào)用name屬性
對應的Dep對象
的notify函數(shù)
,notify遍歷所有watcher屬性,調(diào)用update
去更新視圖
this.name='cobe';
-
Compile解析vue
el
模板中引用的屬性,如我們多次使用了date中的name和age屬性
解析el時
1.每使用的一個屬性就創(chuàng)建一個watcher,watcher會加到對應的dep的subs中;
2.會根據(jù)el內(nèi)容初始化到View(界面顯示)
<script>
//發(fā)布者
class Dep {
constructor() {
this.subs = []; //全部訂閱者watcher
}
//記錄(添加)訂閱者watcher
addSub(watcher) {
console.log(`記錄訂閱者: ${watcher}`)
this.subs.push(watcher)
}
//通知變化
notify(key) {
this.subs.forEach(item => {
if (item.name == key) {
item.update();
}
})
}
}
// 訂閱者
class Watcher {
constructor(name) {
this.name = name;
}
//更新視圖------代碼待補充
update() {
console.log(this.name + '發(fā)生update,執(zhí)行更新視圖')
}
}
const obj = {
name: "cc",
age: 18
}
const dep = new Dep();
Object.keys(obj).forEach(key => {
let value = obj[key];
Object.defineProperty(obj, key, {
set(newValue) {
if(value===newValue){
return false;
}
console.log(`監(jiān)聽: ${key} 值由 ${value} 改為 ${newValue}`)
//通知變化
dep.notify(key)
value = newValue;
},
get() {
console.log(`獲取: ${key} 值`)
/*
添加訂閱者
*/
const watcher = new Watcher(key);
dep.addSub(watcher)
return value
}
})
})
obj.name;
obj.age;
obj.name='aaa';
obj.age=19;
</script>
運行結(jié)果: