{"record":{"id":"202c7101aba974f5","repo":"Meituan-Dianping/mpvue","slug":"avoid-deleting-properties-on-a-vue-instance-or-its","errorCode":null,"errorMessage":"Avoid deleting properties on a Vue instance or its root $data - just set it to null.","messagePattern":"Avoid deleting properties on a Vue instance or its root \\$data - just set it to null\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/core/observer/index.js","lineNumber":268,"sourceCode":"  if (!target.__keyPath) {\n    def(target, '__keyPath', {}, false)\n  }\n  target.__keyPath[key] = true\n  ob.dep.notify()\n  return val\n}\n\n/**\n * Delete a property and trigger change if necessary.\n */\nexport function del (target: Array<any> | Object, key: any) {\n  if (Array.isArray(target) && isValidArrayIndex(key)) {\n    target.splice(key, 1)\n    return\n  }\n  const ob = (target: any).__ob__\n  if (target._isVue || (ob && ob.vmCount)) {\n    process.env.NODE_ENV !== 'production' && warn(\n      'Avoid deleting properties on a Vue instance or its root $data ' +\n      '- just set it to null.'\n    )\n    return\n  }\n  if (!hasOwn(target, key)) {\n    return\n  }\n  delete target[key]\n  if (!ob) {\n    return\n  }\n  if (!target.__keyPath) {\n    def(target, '__keyPath', {}, false)\n  }\n  // Vue.del 删除对象属性，渲染时候把这个属性设置为 undefined\n  target.__keyPath[key] = 'del'\n  ob.dep.notify()","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/Meituan-Dianping/mpvue/blob/6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b/src/core/observer/index.js#L250-L286","documentation":"Warning from Vue.delete / vm.$delete (del in observer/index.js) when the target is a Vue instance or the root $data object. Deleting keys from these breaks the reactive dependency graph, so Vue warns and instead recommends setting the property to null.","triggerScenarios":"Vue.delete(vm, 'someKey'); Vue.delete(this.$data, 'someKey'); this.$delete(this.$data, key) in cleanup logic; using the delete operator on root data keys via a wrapper.","commonSituations":"Cleanup after removing form fields or list items stored at root; state-reset utilities that prune keys; code translated from plain-object state management where delete was routine.","solutions":["Replace the delete with an assignment to null (or undefined semantics via null)","Nest such keys one level down in a data sub-object so Vue.delete works reactively","Declare the key permanently in data and toggle its value instead of removing it","If the item belongs to a list, remove it from the array with splice or $delete on the array index"],"exampleFix":"// before\nthis.$delete(this.$data, 'draft')\n// after\ndata() { return { draft: null } }\nmethods: { clearDraft() { this.draft = null } }","handlingStrategy":"validation","validationCode":"function isSafeDeleteTarget(target) {\n  return target != null && typeof target === 'object' && !target._isVue && !(target.__ob__ && target.__ob__.vmCount)\n}","typeGuard":"function isRootReactive(t) { return t != null && (t._isVue === true || (t.__ob__ && t.__ob__.vmCount > 0)) }","tryCatchPattern":null,"preventionTips":["Set unwanted keys to null instead of deleting them from root data","Nest prunable state under a sub-object so Vue.delete is legal","Keep data shape stable; toggle values rather than keys"],"tags":["vue","reactivity","vue-delete","dynamic-properties"],"backgroundTag":"non-reactive-property-deletion","analyzedSha":"6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b","analyzedAt":"2026-09-02T05:17:40.946Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T11:17:12.671Z"}