操作數(shù)據(jù)推汽,頁面會隨之改變补疑。
實現(xiàn)原理:
Vue在組件和實例初始化的時候,會將data里的數(shù)據(jù)進行數(shù)據(jù)劫持(object.definepropty對數(shù)據(jù)做處理)歹撒。被劫持后的數(shù)據(jù)會有兩個屬性:一個叫g(shù)etter莲组,一個叫setter。[在生成vue實例時栈妆,為對傳入的data進行遍歷,使用Object.defineProperty把這些屬性轉(zhuǎn)為getter/setter.]
getter是使用數(shù)據(jù)的時候觸發(fā)厢钧,setter是在修改數(shù)據(jù)的時候觸發(fā)鳞尔,修改數(shù)據(jù)的時候觸發(fā)setter,同時也觸發(fā)了底層的watcher監(jiān)聽早直,通知dom修改刷新寥假。
每個vue實例都有一個watcher實例,它會在實例渲染時記錄這些屬性霞扬,并在setter觸發(fā)時重新渲染糕韧。
export default {
name: "test",
components: {},
data() {
return {
data0:{
name:"yyp"
}
}
},
methods: { },
mounted: function () {
let data1 ={name:1};
console.log("初始化時就定義的的name,會有g(shù)etter和setter屬性:",this.data0);
console.log("初始化后新定義的name喻圃,沒有g(shù)etter和setter屬性:",data1);
Object.defineProperty(data1,'age',{
get(){},
set(){}
});
console.log("被Object.defineProperty處理過的data萤彩,age屬性有g(shù)etter和setter屬性:",data1)
},
created(){ }
}
三次console.log的結(jié)果如下:
Object.definepropty
是es5中的一個方法,這也就是 Vue 不支持 IE8 以及更低版本瀏覽器的原因斧拍。處理數(shù)據(jù)雀扶,給數(shù)據(jù)賦予getter和setter。
正常情況下肆汹,這兩個方法都不會觸發(fā)愚墓,當我們給數(shù)據(jù)賦值和改變值的情況下會執(zhí)行這兩個函數(shù)。
let middle = 6
Object.defineProperty(data,'age',{
get(){
console.log('獲取age')
return middle
},
set(parmas){
//參數(shù)就是賦值的數(shù)據(jù)
console.log('修改age數(shù)據(jù)',parmas)
middle = parmas
}
})
// 取值的時候觸發(fā)getter
console.log(data.age)
//賦值的時候觸發(fā)setter
data.age = 15
console.log(data.age)
Vue中數(shù)據(jù)變頁面一定變嘛昂勉?
先來看一個小例子:
<div id ='app'>
{{user}}
<hr>
<button @click='changeName'>changeName</button>
</div>
<script>
new Vue({
el:'#app',
data:{
user:{
age:15
}
},
methods: {
changeName(){
this.user.name = '韓梅梅'
console.log(this.user)
}
},
})
</script>
這時候點按鈕浪册,發(fā)現(xiàn)改變不了name的值,所以打開控制看一下
我們會發(fā)現(xiàn)只有age有g(shù)etter和setter岗照,name沒有村象,Vue 無法檢測到對象屬性的添加或刪除,所以沒法進行響應(yīng)式改變數(shù)據(jù)攒至。
Vue 不允許動態(tài)添加根級別的響應(yīng)式屬性煞肾。但是,可以使用 Vue.set(object, propertyName, value)方法向嵌套對象添加響應(yīng)式屬性嗓袱。
兩種情況新添加的屬性都有沒有g(shù)etter和setter籍救,數(shù)據(jù)變頁面也不變:
- 對象數(shù)據(jù)的添加
- 數(shù)組長度的改變
解決方式:動態(tài)的往里面添加數(shù)據(jù),使用this.$set方法
methods: {
changeName(){
// this.user.name = '韓梅梅'
// set 將數(shù)據(jù)用 object.defainPropty進行處理 添加getter和setter
this.$set(this.user,'name','韓梅梅')
console.log(this.user)
}
}
這樣我們就能在頁面上看到新增的屬性