vue3的v-model

摘要

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

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

  2. 具体的变化内容

组件上单个v-model

组件上单个v-model别名

组件上多个v-model

组件上v-model自定义修饰符

  1. 小结

历史回顾

Vue 2.0

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

<son-com v-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>

在组件上的v-model的自定义修饰符

不用羡慕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中的两个问题,并有一个新的创新点

原2.X中只能有一个v-mode,现在可以有多个
原2.X中要单独学习v-model和sync,理解成本较高,现在统一起来了。
创新点是:你可以自已添加修饰符了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值