实现组件v-model双向绑定:Vue2.x VS Vue3.x

这是我参与新手入门的第2篇文章

前文写了深入学习v-model的学习,今天分享下组件上v-model实现vue3.x与vue2.x的区别在哪。

前序

上文讲了v-model是v-bind和v-on的结合体如下:


<!-- v-model -->
<input type="text" v-model="value">

<!-- v-bind 和 v-on -->
<input type="text" :value="value" @input="value = $event.target.value">

复制代码

这两行代码实现的功能是相同的。

正篇

vue2.x 未与model选项的结合

我们先写一个son组件:

<template>
  <div class="son">
  <!-- 这里的v-bind="$attrs"是继承了其他各位的attribute(属性) 这里: type='text' -->
    <input v-bind="$attrs" :value="value" @input="update">
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: String
    }
  },
  methods: {
    update(e) {
      this.$emit('input', e.target.value)
    }
  },
}
</script>
复制代码

父组件使用子组件实现v-model:

<template>
  <div class="parent">
    <!-- type='text' 通过 v-bind="$attrs" 传给了input -->
    <son type='text' v-model="value"></son>
  </div>
</template>

<script>
import son from './son.vue'
export default {
  components: {
    son
  },
  data() {
    return {
      value: 'false'
    }
  },
}
</script>
复制代码

vue2.x与model选项的结合

是不是以为前面就结束了,不!还有内容。前面说v-model是v-bind和v-on的结合,当我们把input类型改成checkbox是后你会发现是没有实现数据的双向绑定。

更改代码

<template>
  <div class="son">
    <!-- 这里的v-bind="$attrs"是继承了其他各位的attribute(属性) -->
    <input v-bind="$attrs" :checked="value" @change="update">
  </div>
</template>

<script>
export default {
  props: {
    value: {
      type: Boolean
    }
  },
  methods: {
    update(e) {
      this.$emit('change', e.target.checked)
    }
  },
}
</script>

<template>
  <div class="parent">
    <!-- type='text' 通过 v-bind="$attrs" 传给了input -->
    <son type='checkbox' v-model="value"></son>
  </div>
</template>

<script>
import son from './son.vue'
export default {
  components: {
    son
  },
  data() {
    return {
      value: false
    }
  },
}
</script>
复制代码

这里为什么不能实现呢?

原因:因为v-model是v-bind和v-on的结合默认v-bind是绑定的value,v-on是绑定input事件,在第一个代码中input类型为text时候value和input正好对应上去,然后在类型为checkbox的绑定值为checked与change,因此无效。

注意点:

text和textarea元素使用value属性和input事件
checkbox和radio使用checked属性和change事件
select使用value和change事件

因此在vue2.2新增了model选项。如此就可以更改v-model它们的默认项:

<template>
  <div class="son">
    <!-- 这里的v-bind="$attrs"是继承了其他各位的attribute(属性) -->
    <input v-bind="$attrs" :checked="value" @change="update">
  </div>
</template>

<script>
export default {
  model: {
    prop: 'value',
    event: 'change'
  },
  props: {
    value: {
      type: Boolean
    }
  },
  methods: {
    update(e) {
      this.$emit('change', e.target.checked)
    }
  },
}
</script>
复制代码

此处只给子组件代码,父组件的代码还是前面一个,未进行修改。

vue3.x的实现

由于之前所说v-model结合.sync修饰符的特点因此就无需model的选项,此处只贴上checkbox类型的代码。

son:

<template>
  <input type="checkbox" :checked="modelValue" @change="change" >
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
   props: {
       modelValue: {
           type: Boolean
       }
    },
   setup(props, context) {
        const change = (e) => {
            // 这里再扯下使用'update:modelValue'是生成了@update:modelValue的事件
            context.emit('update:modelValue', e.target.checked)
        }
        return {
            change
        }
    }
})
</script>
复制代码

parent:

<template>
  <div>
    {{ value }}
    <son v-model="value"></son>
  </div>
</template>

<script lang='ts'>

import { ref } from 'vue'
import son from './son.vue';

export default {
  components: {
    son
  },
  setup() {
    const value = ref(false)
    return {
      value
    }
  },
}
</script>
复制代码

总结

  • vue2.x的v-model默认绑定的是value值input事件

  • vue2.x改变默认值与事件使用model选项

  • vue3.x 由于结合.sync因此可以直接更改,因为生成对应的事件。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享