- MVVM
在說MVVM之前我們首先使用一下Object.defineProperty()方法。
let frank = {
_data: {
name: 'frank',
age: 18
}
}
Object.defineProperty(frank,'age',{
get: function(){
console.log('frank.age被讀取了')
return frank._data.age
//讀age的時候,返回上面那個,為什么我們會多添加一個_data,然后返回的也是frank._data.age,而不是frank.age,可以修改嘗試一下,無限循環。
},
set: function(xxx){
console.log('frank.age被設置了')
frank._data.age = xxx
console.log(frank)
}
})
當我們寫下這段代碼時,frank會添加一個新的屬性age,然后當我們讀取或改變這個屬性的時候,都會有相應的通知。
frank.age //'frank.age被讀取了'
frank.age = 20 //'frank.age被設置了'
接下來,我們在html中添加一個form表單,其中含有一些input元素。
<form >
<p>姓名<input type="text" name="name"></p>
<p>年齡<input type="number" name="age"></p>
<input type="submit" value="提交">
</form>
將JavaScript中的代碼改成:
let frank = {
_data: {
name: 'frank',
age: 18
}
}
for(let key in frank._data){
Object.defineProperty(frank,key,{
get: function(){
console.log('frank.'+key+'被讀取了')
return frank._data[key]
},
set: function(xxx){
console.log('frank.'+key+'被設置了')
//當我修改frank的屬性時,input中的值會立即改變
$('input[name='+key+']').val(xxx)
frank._data[key] = xxx
console.log(frank)
}
})
}
$('form').on('input','input[name]',function(e){
let $input = $(e.target)
let name = $input.attr('name')
let val = $input.val()
//當我修改視圖中的值時,frank中的值會立即改變
frank[name] = val
})
$('input[name="name"]').val(frank.name)
$('input[name="age"]').val(frank.age)
上面的代碼基本實現了數據層M和視圖層V的相互交互,兩頭相互監聽,一旦一方改變,另一方就會有變化。上面的defineProperty和我們DOM事件都是同步的。
缺點:
- MVVM里一個缺點就是V和M是同步的,當我們有一點改變時,另一方都會立馬改變,這樣會非常占用cpu。如果用戶頻繁的改動就會造成卡頓。
- 另一個缺點就是,如果我們的html里有
<p>愛好<input type="text" name="hobby"></p>
而_data里面沒有相應的屬性值,我們就不能設置其與數據的同步,這時候,我們需要一個API,將hobby設置到_data和frank中
createGetAndSet('hobby',0)