谈谈 Vue 中的 v-model 与 sync

  |   0 评论   |   0 浏览   |   Erioifpud

v-model

首先谈谈 v-model,这是 Vue 中非常常见的指令,用于给组件变量进行”双向绑定“,也是一个语法糖,默认情况下把他展开后结果是:

<Child v-model="text"/>
<!-- 等同于 -->
<Child :value="text" @input="text = $event"/>

实际上就是由一个 v-on 与 一个 v-bind 构成的。

为什么说是默认情况下呢?因为例子中的 :value@input 是可以使用 model 选项自定义的,比如:

export default {
  model: {
    prop: 'content',
    event: 'change'
  }
}
<Child v-model="text"/>
<!-- 这个时候 v-model 就等同于 -->
<Child :content="text" @change="text = $event"/>

题外话,上面提到的 $event 表示的是在 Child 中调用 $emit 时带出来的参数,如以下片段:

<Child @input="onInput"/> <!-- 等同于 onInput($event) -->
<Child @input="onInput('username', $event)"/>

只为 @input 提供一个函数名称作为变量时,Vue 会自己将实际参数传入函数的第一个形参,但要自定义传参顺序时,可以使用 $event 来灵活表示了。

sync

说实话,这个修饰符我用得很少,不是因为他没有用,实际上他和 v-model 的功能基本上(为什么是基本,下文有解释)是一样的,但是 v-model 在一个组件上只能出现一次,试想一下,如果你需要双向绑定多个变量怎么办?最基础的写法如下:

<Calendar
  v-model="month"
  :year="year"
  @year-change="onYearChange"
  :date="date"
  @date-change="onDateChange"
/>

这样写明显很繁琐蛋疼,所以就有了 sync 这个语法糖,如下:

<!-- 刚刚的组件可以被简写成 -->
<Calendar
  v-model="month"
  :year.sync="year"
  :date.sync="date"
/>

还没完,和 v-model 一样,还需要在子组件中手动 emit 一下,格式也很特殊,如 $emit('update:year'),其中的“update:”是必需的,这样 sync 才能自动捕获这个事件。

<Child :content.sync="text"/>
<!-- 会被解析成 -->
<Child :content="text" @update:content="text = $event"/>

使用场景

回到前文提到的 v-modelsync 基本一样,为什么是基本呢?因为 sync 不能用在 HTML 表单元素上,关键在于 v-model 的实现,他会自动为不同的表单元素监听不同的事件,但 sync 不会,而且 sync 要求的事件名称格式为 update:propName,HTML 表单元素并不会抛出这样的事件。

在只需要绑定一个变量时,那当然优先选择 v-model,在需要绑定多个变量时,考虑 v-modelsync 一起使用,如果 sync 无法生效,那么就只能通过显式监听事件修改变量去实现了。


标题:谈谈 Vue 中的 v-model 与 sync
作者:Erioifpud
地址:https://blog.doiduoyi.com/articles/1598409443109.html

评论

发表评论