VueJs表单新增提交返回Observer而非Object报错问题求助
问题根本原因
- Vue 2 响应式机制的正常表现:所有定义在
data()返回值中的引用类型数据,都会被Vue自动加上Observer响应式包装,这层包装是不可枚举的内部属性,正常情况下Axios序列化请求体时会自动忽略,不会直接导致接口报错。 - 核心逻辑错误1:
beforeMount钩子中编辑模式的判断条件使用了错误的或运算符||,你实际需要的是且运算符&&,只有当传入的parentIngredient是不为空的普通对象时才触发编辑逻辑。 - 核心逻辑错误2:新增模式下,
data()中初始化的ingredient只声明了ing_name一个字段,其余表单字段(比如ing_cal)都是通过v-model动态添加到响应式对象上的,未提前声明的响应式字段可能出现序列化异常,或者用户未输入时字段值为undefined被序列化丢弃,最终导致后端接收到的字段缺失/类型错误,这才是你接口报错的真实原因。 - 编辑模式表现正常的原因:编辑模式下传入的
parentIngredient已经包含所有完整字段,解构赋值给this.ingredient时所有字段已经存在,不需要动态新增,不存在字段缺失问题,实际上编辑模式下的ingredient同样带有Observer包装,你误以为没有只是因为它没有触发报错。 - 你之前用
JSON.stringify/parse无效的原因:你把转换后的普通对象又赋值回了this.ingredient这个响应式属性,Vue会自动给新赋值的对象重新套上Observer包装,所以永远都会看到Observer标记。
修复方案
- 修正编辑模式判断条件
beforeMount () { // 替换||为&&,仅当parentIngredient是不为空的普通对象时进入编辑模式 if (Object.keys(this.parentIngredient).length !== 0 && this.parentIngredient.constructor === Object) { this.ingredient = { ...this.parentIngredient } this.buttonLabel = 'Modifier' this.buttonType = 'is-info' } },
- 提前声明所有表单字段
在data()的ingredient初始化时,把所有表单用到的字段全部提前声明,给对应类型的默认值,避免动态新增响应式字段:
data () { return { // 其他属性省略 ingredient: { ing_name: '', ing_cal: 0, // 数字类型字段给0作为默认值 // 把其他表单用到的所有字段都在此处提前定义 }, } },
- 提交前生成非响应式的提交数据(可选,彻底规避Observer影响)
如果需要完全剥离响应式属性,不要修改原响应式对象,单独生成提交用的普通对象即可:
async addIngredientToDB () { this.$v.$touch() if (this.$v.$invalid) { this.submitStatus = 'ERROR' return } this.submitStatus = 'VALID' this.ingredient.ing_name = this.ingredient.ing_name.toLowerCase() // 单独生成提交数据,不要赋值回this.ingredient const submitData = JSON.parse(JSON.stringify(this.ingredient)) if (!this.isEditing) { await this.$axios.post('/api/ingredient', submitData) // 后续逻辑省略 } else { await this.$axios.put(`/api/ingredient/${this.ingredient.id}`, submitData) // 后续逻辑省略 } this.$emit('callback') this.$emit('close') }
内容的提问来源于stack exchange,提问作者Luc Simons
相关产品推荐
相关产品推荐

