如何通过自定义$emit事件更新多复选框绑定的数组类型v-model?
解决方案
问题原因
你之前直接将点击事件对象e通过input事件 emit 给父组件,Vue的v-model默认会将input事件的第一个参数直接赋值给绑定的变量,才会出现fields被替换为PointerEvent对象的问题。自定义组件实现数组型v-model的增删逻辑,需要你自己基于父组件传入的value(v-model绑定值对应的props)处理后,emit完整的新数组即可。
代码修改
1. 修正主组件属性绑定错误
原代码中:name="email"会将email当作变量读取,会触发变量未定义报错,要传字符串的话可以去掉冒号,或者用引号包裹变量值:
<template> <div> <helper-switch name="email" v-model="fields"></helper-switch> <helper-switch name="phone" v-model="fields"></helper-switch> <div> {{ fields }} </div> </div> </template> <script> import helperSwitch from './input/HelperSiwtch.vue' export default { components:{ helperSwitch, }, data() { return { fields:[] } } } </script>
2. 子组件helper-switch修改
<template> <div> <label for="c1">Field</label> <input type="checkbox" id="c1" v-model="fieldBool" @change="updateFields" /> <label for="c2">Required</label> <input type="checkbox" id="c2" v-model="requiredBool" @change="updateFields" /> </div> </template> <script> export default { methods: { updateFields() { // 拷贝父组件传入的数组,不直接修改props符合单向数据流 const newFields = [...this.value] // 查找当前name对应的项是否已存在于数组中 const existIndex = newFields.findIndex(item => item.name === this.name) if (this.fieldBool) { // 选中Field的情况:更新或新增对应项 const item = { name: this.name, required: this.requiredBool } if (existIndex > -1) { newFields.splice(existIndex, 1, item) } else { newFields.push(item) } } else { // 取消选中Field的情况:删除对应项 if (existIndex > -1) { newFields.splice(existIndex, 1) } } // emit新数组,v-model会自动更新父组件的fields this.$emit('input', newFields) }, }, props: { name: String, value: Array }, data() { return { fieldBool: false, requiredBool: false, }; }, }; </script>
实现说明
- 监听两个复选框的
change事件而非click事件,更符合复选框状态变更的触发逻辑 - 子组件不会直接修改父组件传入的
value属性,拷贝后修改再emit,符合Vue单向数据流规范 - 勾选Field复选框时会自动将
{name: 传入的name值, required: Required复选框状态}的对象加入数组,取消勾选则移除对应项 - 修改Required复选框的状态也会同步更新数组中对应项的required属性
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

