vm.$delete()
vm.$delete用法見官網。
為什么需要Vue.delete()?
在ES6之前, JS沒有提供方法來偵測到一個屬性被刪除了, 因此如果我們通過delete刪除一個屬性, Vue是偵測不到的, 因此不會觸發數據響應式。
見下面的demo。
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Vue Demo</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app"> 名字: {{ user.name }} 年紀: {{ user.age }} <button @click="addUserAgeField">刪除一個年紀字段</button> </div> <script> const app = new Vue({ el: "#app", data: { user: { name: "test", age: 10 } }, mounted() {}, methods: { addUserAgeField() { // delete this.user.age; // 這樣是不起作用, 不會觸發數據響應式更新 this.$delete(this.user, 'age') // 應該使用 } } }); </script> </body></html>源碼分析內部實現
源碼位置vue/src/core/instance/state.js的stateMixin方法
export function stateMixin (Vue: Class<Component>) { ... Vue.prototype.$set = set Vue.prototype.$delete = del ...}然后查看del函數位置, vue/src/core/observer/index.js。
/** * Delete a property and trigger change if necessary. * target: 將被刪除屬性的目標對象, 可以是對象/數組 * key: 刪除屬性 */export function del (target: Array<any> | Object, key: any) { // 非生產環境下, 不允許刪除一個原始數據類型, 或者undefined, null if (process.env.NODE_ENV !== 'production' && (isUndef(target) || isPrimitive(target)) ) { warn(`Cannot delete reactive property on undefined, null, or primitive value: ${(target: any)}`) } // 如果target是數組, 并且key是一個合法索引,通過數組的splcie方法刪除值, 并且還能觸發數據的響應(數組攔截器截取到變化到元素, 通知依賴更新數據) if (Array.isArray(target) && isValidArrayIndex(key)) { target.splice(key, 1) return } // 獲取ob const ob = (target: any).__ob__ // target._isVue: 不允許刪除Vue實例對象上的屬性 // (ob && ob.vmCount): 不允許刪除根數據對象的屬性,觸發不了響應 if (target._isVue || (ob && ob.vmCount)) { process.env.NODE_ENV !== 'production' && warn( 'Avoid deleting properties on a Vue instance or its root $data ' + '- just set it to null.' ) return } // 如果屬性壓根不在對象上, 什么都不做處理 if (!hasOwn(target, key)) { return } // 走到這一步說明, target是對象, 并且key在target上, 直接使用delete刪除 delete target[key] // 如果ob不存在, 說明target本身不是響應式數據, if (!ob) { return } // 存在ob, 通過ob里面存儲的Dep實例的notify方法通知依賴更新 ob.dep.notify()}
新聞熱點
疑難解答
圖片精選