• vue自定义组件实现v-model双向数据绑定


    一、Vue2 实现自定义组件双向数据绑定

    v-model 实现双向数据绑定

      在vue2中,子组件上使用v-model的值默认绑定到子组件的props.value属性上,由于子组件不能改变父组件传来的属性,所以需要通过$emit触发事件使得父组件中数据的变化,然后再同步到子组件。vue2默认触发v-model数据变化的事件为input

    使用如下:

    子组件MySon

    1. <template>
    2.  <div>
    3.    <div>双向数据绑定:{{$props.value}}div>
    4.    <div><button @click="addValue">点击++button>div>
    5.  div>
    6. template>
    7. <script>
    8. export default {
    9.  name: "MySon",
    10.  props: ['value'],
    11.  methods: {
    12.    addValue() {
    13.      // 触发父组件中v-model绑定数据的变化,由于不能改变props数据中的值,所以不要写this.$props.value++这样的操作
    14.      this.$emit('input', this.$props.value + 1)
    15.   }
    16. }
    17. }
    18. script>

    如果希望改变接收v-model的属性或改变触发v-model数据变化的事件,可通过model:{}配置实现,如:

    1. <template>
    2.  <div>
    3.    <div>双向数据绑定:{{$props.value666}}div>
    4.    <div><button @click="addValue666">点击++button>div>
    5.  div>
    6. template>
    7. <script>
    8. export default {
    9.  name: "MySon",
    10.  props: ['value666'],
    11.  // --> 配置接收v-model数据的属性以及改变数据的事件 <--
    12.  model: {
    13.    prop: 'value666',
    14.    event: 'updateValue666'
    15. },
    16.  methods: {
    17.    addValue666() {
    18.      this.$emit('updateValue666', this.$props.value666 + 1)
    19.   }
    20. }
    21. }
    22. script>

    父组件

    1. <template>
    2.  <div id="app">
    3.    <MySon v-model="num">MySon>
    4.  div>
    5. template>
    6. <script>
    7. import MySon from "@/components/MySon.vue";
    8. export default {
    9.  name: 'App',
    10.  components: {
    11.    //注册子组件
    12.    MySon
    13. },
    14.  watch: {
    15.    // 监视num数据的变化  
    16.    num(newValue, oldValue) {
    17.      console.log('num: ' + oldValue + ' -> ' + newValue)
    18.   },
    19. },
    20.  data() {
    21.    return {
    22.      num: 10,
    23.   }
    24. },
    25. }
    26. script>

    .sync 实现子组件多个数据双向绑定

    Vue2中使用v-model只能使用一次,如果要实现多个双向数据绑定,可以借助.sync修饰,使用语法为 :属性.sync="数据" ,用这种绑定代替v-model,触发数据改变的事件为update:属性名

    使用如下:

    子组件

    1. <template>
    2.  <div>
    3.    <div>sync双向数据绑定:{{$props.data}}div>
    4.    <div><button @click="addData">点击++button>div>
    5.  div>
    6. template>
    7. <script>
    8. export default {
    9.  name: "MySon",
    10.  // 用props.data属性接收双向绑定的数据  
    11.  props: ['data'],
    12.  methods: {
    13.    addData() {
    14.      // 触发 update:data 事件改变父组件中绑定的值  
    15.      this.$emit('update:data', this.$props.data + 1)
    16.   }
    17. }
    18. }
    19. script>

    父组件

    1. <template>
    2.  <div id="app">
    3.      
    4.    <MySon :data.sync="num">MySon>
    5.  div>
    6. template>
    7. <script>
    8. import MySon from "@/components/MySon.vue";
    9. export default {
    10.  name: 'App',
    11.  components: {
    12.    MySon
    13. },
    14.  watch: {
    15.    num(newValue, oldValue) {
    16.      console.log('num: ' + oldValue + ' -> ' + newValue)
    17.   }
    18. },
    19.  data() {
    20.    return {
    21.      num: 10
    22.   }
    23. },
    24. }
    25. script>

    至于为什么子组件要通过$emit('update:属性名', 数据);来触发父组件数据变化,原因如下:

    1. <MySon :data.sync="num">MySon>
    2. ||
    3. \/
    4. 等价于
    5. <MySon :data="num" @update:data="(newData) => {num = newData}">MySon>

    二、Vue3 实现双向数据绑定

    在Vue3中,v-model可以实现多个数据双向数据绑定,同时.sync修饰符已经不再生效。

    v-model 实现双向数据绑定

    vue3中子组件上使用v-model绑定的数据默认传到子组件的props.modelValue属性上(vue2是props.value属性),并且默认触发数据变化的事件为update:modelValuevue2为input

    使用如下:

    子组件

    1. <template>
    2.  <div>
    3.    <div>双向数据绑定modelValue:{{props.modelValue}}div>
    4.    <div><button @click="addModelValue">点击++button>div>
    5.  div>
    6. template>
    7. <script setup>
    8.  // props.modelValue接收v-model绑定的数据
    9.  const props = defineProps(['modelValue'])
    10.  const emit = defineEmits(['update:modelValue'])
    11.  function addModelValue(){
    12.    // 触发父组件中双向绑定数据的变化
    13.    emit('update:modelValue', props.modelValue + 1)
    14. }
    15. script>

    父组件

    1. <template>
    2.  <Son v-model="num">Son>
    3. template>
    4. <script setup>
    5.  import {ref, watch} from "vue";
    6.  import Son from "@/components/Son.vue";  
    7.    
    8.  const num = ref(0)
    9.  // 监视num数据变化
    10.  watch(num, (newValue, oldValue) => {
    11.    console.log('num: ' + oldValue + '->' + newValue)
    12. })
    13. script>

    v-model: 属性 实现多个数据双向绑定

    数据绑定语法:v-model:属性="数据"

    触发数据变化的事件:update:属性

    使用如下:

    子组件

    1. <template>
    2.  <div>
    3.    <div>双向数据绑定data:{{props.data}}div>
    4.    <div><button @click="addData">点击++button>div>
    5.  div>
    6. template>
    7. <script setup>
    8.  const props = defineProps(['data'])
    9.  const emit = defineEmits(['update:data'])
    10.  const addData = () => {
    11.    emit('update:data', props.data + 1)
    12. }
    13. script>

    父组件

    1. <template>
    2.  
    3.  <Son v-model:data="num">Son>
    4. template>
    5. <script setup>
    6.  import {ref, watch} from "vue";
    7.  import Son from "@/components/Son.vue";
    8.  const num = ref(0)
    9.  watch(num, (newValue, oldValue) => {
    10.    console.log('num: ' + oldValue + '->' + newValue)
    11. })
    12. script>

  • 相关阅读:
    《web课程设计》基于HTML+CSS+JavaScript典的中医药大学网(11个页面)
    Redis概述
    2023年数维杯数学建模A题河流-地下水系统水体污染研究求解全过程文档及程序
    这些好用的设计素材网,你一定要知道。
    基于智能优化算法实现自动泊车的路径动态规划(Matlab代码实现)
    c++资料匠心精作C++从0到1入门编程(二)- c++核心
    OpenCV(二十六):边缘检测(二)
    模式也能开盲盒,”盲返“模式带动电商平台共享经济
    【云原生 | Docker篇】Docker镜像(image)与服务
    LeetCode-数组-No41缺失的第一个正数
  • 原文地址:https://blog.csdn.net/weixin_74261199/article/details/143362620