{"record":{"id":"6c479ac024f96c1d","repo":"Meituan-Dianping/mpvue","slug":"avoid-adding-reactive-properties-to-a-vue-instance","errorCode":null,"errorMessage":"Avoid adding reactive properties to a Vue instance or its root $data at runtime - declare it upfront in the data option.","messagePattern":"Avoid adding reactive properties to a Vue instance or its root \\$data at runtime - declare it upfront in the data option\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/core/observer/index.js","lineNumber":238,"sourceCode":"\n/**\n * Set a property on an object. Adds the new property and\n * triggers change notification if the property doesn't\n * already exist.\n */\nexport function set (target: Array<any> | Object, key: any, val: any): any {\n  if (Array.isArray(target) && isValidArrayIndex(key)) {\n    target.length = Math.max(target.length, key)\n    target.splice(key, 1, val)\n    return val\n  }\n  if (hasOwn(target, key)) {\n    target[key] = val\n    return val\n  }\n  const ob = (target: any).__ob__\n  if (target._isVue || (ob && ob.vmCount)) {\n    process.env.NODE_ENV !== 'production' && warn(\n      'Avoid adding reactive properties to a Vue instance or its root $data ' +\n      'at runtime - declare it upfront in the data option.'\n    )\n    return val\n  }\n  if (!ob) {\n    target[key] = val\n    return val\n  }\n  defineReactive(ob.value, key, val)\n  // Vue.set 添加对象属性，渲染时候把 val 传给小程序渲染\n  if (!target.__keyPath) {\n    def(target, '__keyPath', {}, false)\n  }\n  target.__keyPath[key] = true\n  ob.dep.notify()\n  return val\n}","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/Meituan-Dianping/mpvue/blob/6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b/src/core/observer/index.js#L220-L256","documentation":"Warning from Vue.set / vm.$set (set in observer/index.js) when the target is a Vue instance or the root $data object. Adding properties to these at runtime cannot be made reactive reliably, so Vue warns and returns the value without making it reactive.","triggerScenarios":"Vue.set(vm, 'newKey', value); Vue.set(this.$data, 'newKey', value); this.$set(this.$data, key, val) for dynamic form fields; assigning new keys onto vm directly after creation and expecting reactivity.","commonSituations":"Dynamic form schemas adding fields after mount; generic key/value editors bound directly to $data; plugins attempting to extend instances post-creation instead of at init.","solutions":["Declare all keys upfront in the data() option, even with placeholder values","If the set of keys is dynamic, nest them: data(){return{fields:{}}} and Vue.set(this.fields, key, val)","Restructure dynamic items into arrays, which Vue can react to via splice/push","If purely non-reactive metadata is needed, store it on this outside data and skip reactivity"],"exampleFix":"// before\nthis.$set(this.$data, 'field_' + i, '')\n// after\nexport default {\n  data() { return { fields: {} } },\n  methods: { addField(i) { this.$set(this.fields, 'field_' + i, '') } }\n}","handlingStrategy":"validation","validationCode":"function isSafeSetTarget(target) {\n  return target != null && typeof target === 'object' && !target._isVue && !(target.__ob__ && target.__ob__.vmCount)\n}\n// only call Vue.set when isSafeSetTarget(target)","typeGuard":"function isVueInstanceOrRootData(t) { return t != null && (t._isVue === true || (t.__ob__ && t.__ob__.vmCount > 0)) }","tryCatchPattern":null,"preventionTips":["Declare every reactive key in data() upfront","Keep dynamic keys in a nested object, not at $data root","Add keys to arrays via push/splice which Vue observes"],"tags":["vue","reactivity","vue-set","dynamic-properties"],"backgroundTag":"non-reactive-property-addition","analyzedSha":"6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b","analyzedAt":"2026-09-02T05:17:40.946Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T11:17:12.671Z"}