在開發過程當中,咱們時常會遇到這樣一種狀況:當vue的data裏邊聲明或者已經賦值過的對象或者數組(數組裏邊的值是對象)時,向對象中添加新的屬性,若是更新此屬性的值,是不會更新視圖的。javascript
根據官方文檔定義:若是在實例建立以後添加新的屬性到實例上,它不會觸發視圖更新。 受現代 JavaScript 的限制 (以及廢棄 Object.observe),Vue 不能檢測到對象屬性的添加或刪除。因爲 Vue 會在初始化實例時對屬性執行 getter/setter 轉化過程,因此屬性必須在 data 對象上存在才能讓 Vue 轉換它,這樣才能讓它是響應。vue
固然針對這種狀況,官方也提供瞭解決方案,以下: Vue 不容許在已經建立的實例上動態添加新的根級響應式屬性 (root-level reactive property)。然而它可使用Vue.set(obj, key, val)方法將響應屬性添加到嵌套的對象上: Vue.set(vm.obj, 'e', 0) 您還可使用 vm.$set 實例方法,這也是全局 Vue.set 方法的別名: this.$set(this.obj, 'e', 2)java
<div>
<h3>展現姓名:<span id="name"></span></h3>
<p>輸入姓名:<input type="text" oninput="inputHandler('name', this.value)" /></p>
<h3>展現電話號碼:<span id="phone"></span></h3>
<p>輸入電話號碼:<input type="text" oninput="inputHandler('phone', this.value)" /></p>
</div>
<script type="text/javascript">
// 須要監聽的對象 ----
var obj = {
name: null
}
// 定義監聽 - Object.defineProperty的實現
for(let key in obj) {
let val = obj[key];
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get() {
return val;
},
set(newValue) {
if(val === newValue) {
return;
}
document.getElementById(key).innerText = newValue;
val = newValue;
}
})
}
var inputHandler = function(key, value) {
obj[key] = value;
}
</script>
複製代碼
<div>
<h3>展現姓名:<span id="name"></span></h3>
<p>輸入姓名:<input type="text" oninput="inputHandler('name', this.value)" /></p>
<h3>展現電話號碼:<span id="phone"></span></h3>
<p>輸入電話號碼:<input type="text" oninput="inputHandler('phone', this.value)" /></p>
</div>
<script type="text/javascript">
// 須要監聽的對象 ----
var obj = {
name: null
}
obj = new Proxy(obj, {
get: function(target, prop) {
console.log('proxy get:', target, prop);
},
set: function(target, prop, value) {
document.getElementById(prop).innerText = value;
target[prop] = value;
console.log('proxy:', target, prop, value);
}
})
var inputHandler = function(key, value) {
obj[key] = value;
}
</script>
複製代碼
運行起來看看,是否是不使用$set,就能實現新增屬性的綁定呢?期待Vue3.0的到來。react