思路
vue.js 是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter玫鸟,在數(shù)據(jù)變動時(shí)發(fā)布消息給訂閱者良风,觸發(fā)相應(yīng)的監(jiān)聽回調(diào)。
那么我們就使用Object.defineProperty()寫個小demo窑多,模擬vue的雙向綁定效果,來借此學(xué)習(xí)一下Object.defineProperty()這個方法
Object.defineProperty(obj, prop, descriptor)
傳入?yún)?shù)
第一個參數(shù):目標(biāo)對象
第二個參數(shù):需要定義的屬性或方法的名字洼滚。
第三個參數(shù):目標(biāo)屬性所擁有的特性埂息。(descriptor)
前兩個參數(shù)不多說了,一看代碼就懂遥巴,主要看第三個參數(shù)descriptor千康,看看有哪些取值
descriptor
他又以下取值,我們簡單認(rèn)識一下铲掐,后面例子拾弃,挨個介紹,
value:屬性的值(不用多說了)
writable:如果為false摆霉,屬性的值就不能被重寫,只能為只讀了
configurable:總開關(guān)豪椿,一旦為false奔坟,就不能再設(shè)置他的(value,writable搭盾,configurable)
enumerable:是否能在for...in循環(huán)中遍歷出來或在Object.keys中列舉出來咳秉。
get:外部取obj的子屬性prop的值時(shí)觸發(fā)的回調(diào)
set:外部給obj的子屬性prop賦值時(shí)觸發(fā)的回調(diào)
注意:在 descriptor 中不能 同時(shí)設(shè)置訪問器 (get 和 set) 和 wriable 或 value,否則會錯鸯隅,就是說想用(get 和 set)澜建,就不能用(wriable 或 value中的任何一個)
demo
我們利用set和get來簡單模擬一下雙向綁定
1.先定義個構(gòu)造函數(shù)
function Vue (opt){
var el=opt.el;
var data=opt.data;
var methods=opt.methods;
var model={};
var keys=Object.keys(data);
for (let i=0;i<keys.length;i++) {
Object.defineProperty(model, keys[i], {
set: function(newValue) {
data[keys[i]]=newValue
change(keys[i])
},
get: function() {
return data[keys[i]]
},
enumerable:true,
configurable:true,
})
}
var inputs=document.querySelector(el).querySelectorAll('input[v-model]')
for (let i=0;i<inputs.length;i++) {
inputs[i].onkeyup=function(){
var v=this.getAttribute('v-model')
model[v]=this.value
change(v)
}
}
var buttons=document.querySelector(el).querySelectorAll('*[v-click]')
for (let i=0;i<buttons.length;i++) {
buttons[i].onclick=function(){
var func=this.getAttribute('v-click')
methods[func]()
}
}
function change(k){
var els=document.querySelector(el).querySelectorAll('*[v-text="'+k+'"]')
for (let j=0;j<els.length;j++) {
els[j].innerHTML=data[k]
}
var inputs=document.querySelector(el).querySelectorAll('input[v-model="'+k+'"]')
for (let j=0;j<inputs.length;j++) {
inputs[j].value=data[k]
}
}
return model
}
2.寫一段簡單的html
<div id="app">
<input type="" name="" value="" v-model="obj"/>
<p v-text="obj"></p>
<input type="" name="" value="" v-model="aaa"/>
<p v-text="aaa"></p>
<button v-click="printObj">打印</button>
</div>
3.實(shí)例化vue方法
var vm=new Vue({
el:'#app',
data:{
obj:'',
aaa:'',
},
methods:{
printObj:function(){
alert(vm.obj)
}
}
})
如上所示,分別定義了obj和aaa兩個字段和一個printObj方法蝌以,來看看效果:
好了炕舵,大功告成!當(dāng)然vue遠(yuǎn)遠(yuǎn)比這個復(fù)雜的多跟畅,這里只是練習(xí)一下Object.defineProperty()這個方法咽筋。