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

21 篇文章 0 订阅

使用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>

展示效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

父组件
<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-option
            v-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官方及各插件库的方案 使用计算属性来保证双向数据流

通过计算属性 修改父组件中的值 让父组件的值发生变化 在去改变子组件的值
在这里插入图片描述

父组件
<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-option
            v-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 = this
        return 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>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值