Vue2.0/3.0 雙向資料系結的實作原理
雙向資料系結簡意 即資料的改變能讓頁面重新渲染
Vue2.0 原理ES5:Object.defineProperty 對資料進行攔截
簡單小案例
<body>
姓名:
<span id="name"></span>
<br />
<input type="text" id="inputName" />
</body>
改變input框的值 讓span里面的值隨之改變 資料的改變可以讓視圖
<script>
let obj ={
name:''
}
Object.defineProperty(obj,'name',{
get(){
return this.name //注意錯誤示范 不可以用this 形成死回圈 要準備一個新的值
},
set(val){
}
})
</script>
正確寫法
<script>
let obj = {
name: ""
};
let newObj = JSON.parse(JSON.stringify(obj));
Object.defineProperty(obj, "name", {
get() {
return newObj.name;
},
set(val) {
if (val === newObj.name) return; //增加判斷優化性能 判斷新值與舊值是否一樣 一樣就回傳 不一樣的話的再次賦值
newObj.name = val;
obServer();
}
});
// 重新賦值的方法
function obServer() {
spanName.innerHTML = newObj.name; //獲取obj.name的值
inputName.value = newObj.name;
}
obServer(); //開始就執行一次
setTimeout(() => {
obj.name = "大左";
}, 1000);
</script>
執行邏輯
setTimeout執行1秒后修改資料 觸發obj.name的set(val) 拿到最新的值給到newObj.name 執行 obServer()方法 拿到最新的值賦值 spanName.innerHTML = newObj.name; inputName.value = newObj.name;

input框的值改變 span框的值隨著改變
inputName.oninput = function() {
obj.name = this.value;
};

這個操作在Vue 里面叫v-model
Vue2.0不足之處
1.需要對原始資料進行克隆 不然死回圈 上面有提到
2.如果我們想給物件中的資料進行get和set的攔截 就要一個個設定 物件中的屬性都要單獨的監聽一下 如果有多個就要回圈遍歷了 分別來監聽了
反看vue2.0中的data
data(){
return{
obj:{}
}
}
this.obj.name='XXX' //這個操作行不通 因為剛開始的時候obj里面沒有name所以就沒有進行監聽 都是以上第二條造成的
ok 那我們再看一下
3.0的特點以及好處
主要用到了SE6里面的proxy
<script>
let obj = {};
obj = new Proxy(obj, {
get(target, prop) {
console.log("D");
return target[prop];
},
set(target, prop, value) {
console.log("Z");
target[prop] = value;
}
}); //監聽整個物件 不需要指定屬性 相當于把物件里所有的屬性都監聽了 So 直接寫整體的set get
</script>
1.獲取obj.name 觸發get 這里沒有name 但是可以走 因為沒有值所以回傳undefine

2. 設定給name值看一下 觸發set

3.再次獲取obj.name看看有沒有值

So 不管你現在物件里有沒有某個屬性 因為這里監聽的是整個物件 物件里面未來有的都有了 彌補2.0不足之處 1.不需要clone 2.也不需要給每一個物件里面的屬性單獨設定 給整體物件設定就ok了 例外方便
再次實作上面2.0的操作
<script>
let obj = {};
obj = new Proxy(obj, {
get(target, prop) {
console.log("D");
return target[prop];
},
set(target, prop, value) {
console.log("Z");
target[prop] = value;
obServer();
}
}); //監聽整個物件 不需要指定屬性 相當于把物件里所有的屬性都監聽了 So 直接寫整體的set get
// 重新賦值的方法
function obServer() {
spanName.innerHTML = obj.name; //獲取obj.name的值
inputName.value = obj.name;
}
obServer(); //開始就執行一次
setTimeout(() => {
obj.name = "大左";
}, 1000);
inputName.oninput = function() {
obj.name = this.value;
};
</script>

如果對你有一點點幫助的話點贊加收藏吧,互動必回噢~~~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/277683.html
標籤:其他
上一篇:Vue---組件詳解
