Vue3的v-model

摘要

vue3.0中对如何在自定义组件上使用v-model进行了重大升级,本文详情列出了变化要点,并给出了示例代码。

内容

1. 历史回顾。v-model的前世今生

2. 具体的变化内容

  • 组件上单个v-model
  • 组件上单个v-model别名
  • 组件上多个v-model
  • 组件上v-model自定义修饰符

    3. 小结

    历史回顾

    Vue 2.0

    v-model 只能绑定在组件的 value 属性上。

    <son-comv-model="msg" />

    也就是说在son-com这个的组件的内部,你只能通过一个名为value的属性来获取父组件中传入的msg的值。

    • {
    • props:['value']
    • }

    这一点其实不太友好:value这个词太没有语义了。所以在后续版本中增加可修改属性名的功能。

    vue 2.2

    在此版本中,组件在定义可以写 model 项,开发者通过这个设置和 v-model 关联的属性和事件。

    具体做法是在组件内部定义一个model项,其中prop用来设置v-model中默认的value的别名, event用来设置v-model中默认的input事件的别名

    • Vue.component('SonCom',{
    • template: `
    • <div>{{checked}} <button @click="$emit('change', false)">设成false</div>
    • `
    • model: {
    • prop: 'checked', // 默认叫value
    • event: 'change' // 默认叫input
    • }
    • }

    Vue 2.x

    一个组件上只能一个v-model。

    当然,你也可以用v-bind.sync来达成多个数据项双向绑定的效果,代码如下:

    • <div id="app">
    • <h2>父组件</h2>
    • {{a}} - {{b}}
    • <son-com v-bind:a.sync="a" v-bind:b.sync="b"></son-com>
    • </div>
    • <script>
    • Vue.component('SonCom', {
    • props:['a', 'b'],
    • template: `
    • <div>
    • {{a}}<button @click="$emit('update:a',100) ">改父中的a</button>
    • {{b}}<button @click="$emit('update:b',200) ">改父中的b</button>
    • </div>
    • `
    • })
    • var vm = new Vue({
    • el: '#app',
    • data: {
    • a: 1,
    • b: 2
    • }
    • })
    • </script>

    Vue 3

    v-bind的.sync修饰符和组件的model选项被删除了,因为你不再需要它们了,具体说明见后文。

    变化内容

    先把明细列出来:

    • 属性以及事件的默认名称变了
    • v-bind 的 .sync 修饰符和组件的 model 选项被移除了,取而代之的是 v-model 参数
    • 支持同一组件同时设置多个 v-model
    • 支持自定义 v-model 修饰符

      在原生input 上的v-model

      它的使用与2.X的版本是一样的,也可以使用修饰符。

      • <script src="https://unpkg.com/vue@next"></script>
      • <div id="app">
      • <h2>父组件</h2>
      • {{a}}
      • <input v-model.trim="a" />
      • </div>
      • <script>
      • const app = Vue.createApp({
      • data() {
      • return{
      • a: 1
      • }
      • }
      • })
      • app.mount("#app")
      • </script>

      在组件上的单个v-model

      请注意,属性名是 modelValue, 事件名是:update:modelValue

      • <script src="https://unpkg.com/vue@next"></script>
      • <div id="app">
      • <h2>父组件</h2>
      • {{a}}
      • <son-com v-model="a"></son-com>
      • <!--等价于:
      • <son-com :modelValue="a" @update:modelValue="a = $event"/>
      • -->
      • </div>
      • <script>
      • const app = Vue.createApp({
      • data() {
      • return{
      • a: 1
      • }
      • },
      • components: {
      • SonCom: {
      • props:['modelValue'],
      • template: `
      • <div>
      • {{modelValue}}<button @click="$emit('update:modelValue',100) ">改父中的a</button>
      • </div>
      • `
      • }
      • }
      • })
      • app.mount("#app")
      • </script>

      这种写法就与2.X中的.sync的写法比较一致了。

      在组件上的v-model绑定别名

      下面将传入子组件中的属性从固定的modelValue改个名字。

      • <script src="https://unpkg.com/vue@next"></script>
      • <div id="app">
      • <h2>父组件</h2>
      • {{a}}
      • <son-com v-model:msg="a"></son-com>
      • <!-- 在子组件内部,传入的属性是msg,在父组件中绑定的值是a -->
      • </div>
      • <script>
      • const app = Vue.createApp({
      • data() {
      • return{
      • a: 1
      • }
      • },
      • components: {
      • SonCom: {
      • props:['msg'],
      • template: `
      • <div>
      • {{msg}}<button @click="$emit('update:msg',100) ">改父中的a</button>
      • </div>
      • `
      • }
      • }
      • })
      • app.mount("#app")

       

      组件上的多个v-model

      终于可以写多个v-model了

      • <script src="https://unpkg.com/vue@next"></script>
      • <div id="app">
      • <h2>父组件</h2>
      • {{a}} - {{b}}
      • <son-com v-model:a="a" v-model:b="b"></son-com>
      • </div>
      • <script>
      • const app = Vue.createApp({
      • data () {
      • return { a: 1, b: 2 }
      • },
      • components: {
      • SonCom: {
      • props:['a', 'b'],
      • template: `
      • <div>
      • {{a}}<button @click="$emit('update:a',100) ">改父中的a</button>
      • {{b}}<button @click="$emit('update:b',200) ">改父中的b</button>
      • </div>
      • `
      • }
      • }
      • })
      • app.mount("#app")
      • </script>

      不用羡慕trim啦,你可以自已添加修饰符。定义格式:

        <子组件 v-model.修饰符1.修饰符2="绑定值" />

      原理

      在子组件内部,通过定义一个名为 modelModifiers的属性来收集修饰符,它的结果的格式是:

      {   修饰符1:true
           修饰符2:true
      }

      然后在抛出事件之前,就根据这个修饰符来定义自已的逻辑了。

      示例

      • <script src="https://unpkg.com/vue@next"></script>
      • <div id="app">
      • <h2>父组件</h2>
      • {{a}} - {{b}}
      • <son-com v-model.big10="a"></son-com>
      • <son-com v-model="b"></son-com>
      • </div>
      • <script>
      • const app = Vue.createApp({
      • data() {
      • return{
      • a: 1,
      • b: 1
      • }
      • }
      • })
      • app.component('SonCom', {
      • props:['modelValue', 'modelModifiers'],
      • created () {
      • console.log(this.modelModifiers) // {big10: true}
      • },
      • template: `
      • <div>
      • {{modelValue}}<button @click="hClick">改父中的a</button>
      • </div> `
      • ,
      • methods: {
      • hClick () {
      • let val = 100
      • // 写具体的逻辑
      • console.log(this.modelModifiers)
      • if (this.modelModifiers && this.modelModifiers.big10) {
      • val += 10
      • }
      • this.$emit('update:modelValue', val)
      • }
      • }
      • })
      • app.mount("#app")
      • </script>

       

      当然,如果在v-model改了prop的名字,则名字也随之变化。

      如果是: <son-comv-model:foo="a"/>

      则对应的prop及修饰符的名字就会变成: props:['foo','fooModifiers']

      小结

      3.X中的v-model解决了2.X中的两个问题,并有一个新的创新点

      1. 原2.X中只能有一个v-mode,现在可以有多个
      2. 原2.X中要单独学习v-model和sync,理解成本较高,现在统一起来了。

      创新点是:你可以自已添加修饰符了。

      版权声明:
      作者:Joker 链接:http://456787.xyz/archives/201
      文章版权归作者所有,转载请注明出处。
      THE END
      分享
      二维码
      打赏
      < <上一篇
      下一篇>>
      文章目录

      摘要

      内容

      历史回顾

      Vue 2.0

      vue 2.2

      Vue 2.x

      Vue 3

      变化内容

      在原生input 上的v-model

      在组件上的单个v-model

      在组件上的v-model绑定别名

      组件上的多个v-model

      小结

      关闭
      目 录