> 文章列表 > 组件封装v-model .sync在父子组件中实现双向数据绑定 如何处理单向数据流 封装表单组件

组件封装v-model .sync在父子组件中实现双向数据绑定 如何处理单向数据流 封装表单组件

组件封装v-model .sync在父子组件中实现双向数据绑定 如何处理单向数据流 封装表单组件

使用watch监听

组件使用.sync进行数据的绑定 传值子组件时 把值赋值到data的变量中 然后监听该数据的变化 $emit抛出

父组件demo

<template><div><Son :model-value.sync="modelValue" :select-value.sync="selectValue" /></div>
</template><script>
import Son from './son.vue'
export default {name: 'Father',components: {Son},props: {},data() {return {modelValue: '789',selectValue: '1'}}}
</script><style lang="scss" scoped></style>

子组件

<template><div><div style="margin-top: 15px;width: 600px;"><el-input v-model="sonInputValue" placeholder="请输入内容" class="input-with-select"><el-select slot="prepend" v-model="sonSelectValue" placeholder="请选择" style="width: 100px;"><el-option label="餐厅名" value="1" /><el-option label="订单号" value="2" /><el-option label="用户电话" value="3" /></el-select><el-button slot="append" icon="el-icon-search" /></el-input></div></div>
</template><script>
export default {name: 'Son',// 父组件传递过来的值props: {modelValue: {type: String,default: ''},selectValue: {type: String,default: ''}},data() {return {// 子组件绑定的值sonInputValue: this.modelValue,sonSelectValue: this.selectValue}},watch: {// 当子组件绑定的值发生变化时 抛给父组件sonInputValue() {this.$emit('update:modelValue', this.sonInputValue)},sonSelectValue() {this.$emit('update:selectValue', this.sonInputValue)}}
}
</script><style lang="scss" scoped></style>

展示效果

组件封装v-model .sync在父子组件中实现双向数据绑定 如何处理单向数据流 封装表单组件
组件封装v-model .sync在父子组件中实现双向数据绑定 如何处理单向数据流 封装表单组件
组件封装v-model .sync在父子组件中实现双向数据绑定 如何处理单向数据流 封装表单组件

使用绑定对象的方式打破单向数据流实现

父组件

<template><div><Son :model-value.sync="modelValue" /></div>
</template><script>
import Son from './son.vue'
export default {name: 'Father',components: {Son},props: {},data() {return {modelValue: {keyword: '',placeholder: '请输入你查询的关键字',options: [{ label: '视频', value: 'video' },{ label: '文章', value: 'article' },{ label: '用户', value: 'user' }],selectValue: 'video'}}}}
</script><style lang="scss" scoped></style>

子组件

<template><div><div style="margin-top: 15px;width: 600px;"><el-input v-model="modelValue.keyword" :placeholder="modelValue.placeholder" class="input-with-select"><el-select slot="prepend" v-model="modelValue.selectValue" placeholder="请选择" style="width: 100px;"><el-optionv-for="item in modelValue.options":key="item.value":label="item.label":value="item.value"/></el-select><el-button slot="append" icon="el-icon-search" /></el-input></div></div>
</template><script>
export default {name: 'Son',// 父组件传递过来的值props: {modelValue: {type: Object,default: () => { },require: true}},data() {return {}},watch: {}
}
</script><style lang="scss" scoped></style>

参考vue官方及各插件库的方案 使用计算属性来保证双向数据流

通过计算属性 修改父组件中的值 让父组件的值发生变化 在去改变子组件的值
组件封装v-model .sync在父子组件中实现双向数据绑定 如何处理单向数据流 封装表单组件

父组件

<template><div><Son :model-value.sync="modelValue" /></div>
</template><script>
import Son from './son.vue'
export default {name: 'Father',components: {Son},props: {},data() {return {modelValue: {keyword: '',placeholder: '请输入你查询的关键字',options: [{ label: '视频', value: 'video' },{ label: '文章', value: 'article' },{ label: '用户', value: 'user' }],selectValue: 'video'}}}}
</script><style lang="scss" scoped></style>

子组件

<template><div><div style="margin-top: 15px;width: 600px;"><el-input v-model="model.keyword" :placeholder="model.placeholder" class="input-with-select"><el-select slot="prepend" v-model="model.selectValue" placeholder="请选择" style="width: 100px;"><el-optionv-for="item in model.options":key="item.value":label="item.label":value="item.value"/></el-select><el-button slot="append" icon="el-icon-search" /></el-input></div></div>
</template><script>
export default {name: 'Son',// 父组件传递过来的值props: {modelValue: {type: Object,default: () => { },require: true}},data() {return {}},computed: {model: {get() {const _this = thisreturn new Proxy(this.modelValue, {set(obj, name, val) {_this.$emit('update:modelValue', {...obj,[name]: val})return true}})},set(val) {this.$emit('update:modelValue', val)}}},watch: {}
}
</script><style lang="scss" scoped></style>