關(guān)于Vue.js
Vue.js
是一款
MVVM
框架,上手快速簡單易用,通過響應(yīng)式在修改數(shù)據(jù)的時候更新視圖。
Vue.js
的響應(yīng)式原理依賴于
Object.defineProperty
,尤大大在Vue.js
文檔中就已經(jīng)提到過,這也是
Vue.js
不支持
E8
以及更低版本瀏覽器的原因。
Vue
通過設(shè)定對象屬性的
setter/getter
方法來監(jiān)聽數(shù)據(jù)的變化,通過
getter
進行依賴收集,而每個
setter
方法就是一個觀察者,在數(shù)據(jù)變更的時候通知訂閱者更新視圖。
將數(shù)據(jù)data變成可觀察(observable)的
那么Vue
是如何將所有
data
下面的所有屬性變成可觀察的(
observable
)呢?
function
observer(value) {
Object.keys(value).forEach((key) => defineReactive(value, key, value[key] , cb))
}
function
defineReactive (obj, key, val, cb) {
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: ()=>{
/*....
依賴收集等
....*/
},
set:newVal=> {
cb();/*
訂閱者收到消息的回調(diào)
*/
}
})
}
class
Vue {
constructor(options) {
this._data = options.data;
observer(
this._data, options.render)
}
}
let app =
new Vue({
el: '#app',
data: {
text: 'text',
text2: 'text2'
},
render(){
console.log("render");
}
})
為了便于理解,首先考慮一種最簡單的情況,不考慮數(shù)組等情況,代碼如上所示。在
initData
中會調(diào)用
observe
這個函數(shù)將Vue
的數(shù)據(jù)設(shè)置成
observable
的。當(dāng)
_data
數(shù)據(jù)發(fā)生改變的時候就會觸發(fā)
set
,對訂閱者進行回調(diào)(在這里是
render
)。
那么問題來了,需要對app._date.text
操作才會觸發(fā)
set
。為了偷懶,我們需要一種方便的方法通過
app.text
直接設(shè)置就能觸發(fā)
set
對視圖進行重繪。那么就需要用到代理。
代理
我們可以在Vue
的構(gòu)造函數(shù)
constructor
中為
data
執(zhí)行一個代理
proxy
。這樣我們就把data
上面的屬性代理到了
vm
實例上。
_proxy(options.data);/*
構(gòu)造函數(shù)中
*/
/*
代理
*/
function
_proxy (data) {
const that =
this;
Object.keys(data).forEach(key => {
Object.defineProperty(that, key, {
configurable: true,
enumerable: true,
get:
function
proxyGetter () {
return that._data[key];
},
set:
function
proxySetter (val) {
that._data[key] = val;
}
})
});
}
我們就可以用app.text
代替
app._data.text
了。
.js
來源:
稀土掘金