tiantingrui / daily-harvest

记录每日收获
MIT License
2 stars 0 forks source link

Vue3 新特性之 `v-model` #22

Open tiantingrui opened 2 years ago

tiantingrui commented 2 years ago

先简单来看一看 v-model 发生了什么变化

Vue2.x 时代

在组件上使用 v-model 相当于传递了 value 属性并触发了 input 事件:

<TInput v-model="name">
<!--   相当于下面  -->
<TInput :value="name" @input="name = $event">

如果想要改变 v-model 绑定的属性或者事件,需要在子组件内添加一个 model :

// TInput.vue

export default {
  model: {
       prop: 'title',
       event: 'change'

  }

}

这样一改,相当于下面这个组件

<TInput  :title="name" @change="name = $event">

使用 v-bind.sync 实现组件属性的双向绑定

在某些场景下,我们需要实现对组件属性的双向绑定,比如:实现一个弹窗组件,用一个 visible 属性控制弹窗的出现和隐藏,可以在组件内部和外部关闭这个弹窗。官方团队推荐用 update:propName 的方式去解决这个问题。比如上面的 TInput 的例子,我们可以用下面这句话在组件内部改变 title 的值

this.$emit('update:title', 'terry yyds')

然后再父组件监听这个事件

<TInput :title="name" @update:title="name = $event" />

为了方便,.sync这个修饰符便出现了

<TInput :title.sync="name" />

Vue3.x 时代,有点骚气

在 3.x 版本中,在自定义组件上使用 v-model 相当于传递了一个 modelValue 属性以及触发一个 update:modelValue 事件:

<TInput  v-model="name">
<!-- 相当于下面这行 -->
<TInput :modelValue="name" @update:modelValue="name = $event" />

v-model 参数

那么如果响应改变绑定的属性名,只需要给 v-model 传一个参数就好了

<TInput v-model:title='name' />
<!-- 等同于 -->
<TInput :title="name" @update:title="name = $event" />

骚!是真的骚!!!

不仅如此,这个写法还彻底代替了 .sync 修饰符,并且支持统一组件绑定多个 v-model

<TInput v-model:title="name"  v-model:content="info">
<!-- 相当于 -->
<TInput
    :title="name"
    @update:title="name = $event"
    :content="info"
    @update:content="info = $event"
/>