vue響應式資料繫結最簡單的實現
原文在我的github前端部落格,地址[github.com/dzfrontend/…],歡迎訂閱...
vue響應式資料繫結:當資料發生改變,檢視自動更新
原理
把一個普通的js物件傳給vue例項的data選項,vue講遍歷此物件的所有屬性,使用Object.defineProperty把這些屬性轉化成getter和setter,vue內部會對資料進行劫持,在屬性被訪問和修改的時候進行通知。
Object.defineProperty
作用:
在一個物件上定義一個新屬性,或者修改一個物件的現有屬性。
語法:
Object.defineProperty(obj, obj.key, {
// 資料描述
value: 該屬性對應的值 預設undefined,
writable: 該屬性是否可以被重寫 預設false,
enumerable: 該屬性是否可以被列舉(是否可以被for-in遍歷) 預設false,
configurable: 該屬性是否可以被刪除 預設false,
// 訪問器描述
get: function(){
}
set: function(newValue) {
}
})
複製程式碼
相容性:
屬於es5中的方法,但是不相容ie8,這也是vue不相容ie8的原因。
實現最簡單的響應式資料繫結
在傳統的dom操作方式中,資料發生變化,頁面不會自動更新變化,需要再次進行dom操作才能讓檢視發生變化。
<div id="app">
<button id="btn">改變資料</button>
<h5 id="title"></h5>
</div>
<script>
var data = {
title: '資料'
}
var title = document.getElementById('title');
var btn = document.getElementById('btn');
title.innerHTML = data.title;
btn.onclick = function() {
data.title = '資料發生變化';
title.innerHTML = data.title; // 再次改變dom節點的innerHTML
}
</script>
複製程式碼
上面例子中,data.title繫結到了id為title的dom節點中,當點選button的時候,改變data.title,需要重新改變dom,檢視才會發生變化。
要想實現vue響應式資料繫結,需要用到Object.defineProperty, 使用資料的時候,進行資料劫持,把屬性轉成訪問器的方式,然後vue處理檢視更新。
<div id="app">
<button id="btn">改變資料</button>
<h5 id="title"></h5>
</div>
<script>
var data = {
title: '資料'
}
// 資料劫持
function observer(obj) {
Object.keys(obj).forEach(function(item){
defineReactive(obj, item, obj[item]);
})
}
function defineReactive(obj, key, value) {
Object.defineProperty(obj, key, {
get() {
return value;
},
set(newValue) {
value = newValue;
title.innerHTML = value; // 更新檢視,vue內部處理,這裡是簡寫
}
})
}
observer(data);
var title = document.getElementById('title');
var btn = document.getElementById('btn');
title.innerHTML = data.title;
// 更新檢視,直接運算元據,不用進行dom操作
btn.onclick = function() {
data.title = '資料發生變化';
}
</script>
複製程式碼
上面例子中,observer(data)對資料data裡面的每一個屬性進行劫持,data裡面屬性title的值發生改變時,在Object.defineProperty裡的setter會獲取到發生改變的值,vue內部然後進行檢視更新;
當點選button,只需要改變data.title而不用進行dom操作,vue內部會自動處理檢視更新。
full examples at here.
原文在我的github前端部落格,地址[github.com/dzfrontend/…],歡迎訂閱...