我们知道,在vue中,使用v-model可以实现双向绑定,但是其中的原理是如何的呢?今天我们就来一探究竟。

其实在vue中,在使用v-model绑定数据之后,既绑定了数据,又添加了事件监听,这个事件就是input事件。

例如官方文档给出:

<input v-model="something">

这不过是以下示例的语法糖:

<input
  v-bind:value="something"
  v-on:input="something = $event.target.value">

这就解释了为什么在input元素使用v-model绑定数据后,可以实现双向绑定,因为输入的时候会触发元素的input事件。

而通过这个语法糖,我们可以轻易的实现子组件和父组件数据的双向绑定,下面用代码演示。

父组件

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <!--<router-view/>-->
    <car v-model="index"></car>
    <div>{{index}}</div>
  </div>
</template>

<script>
import Car  from "./car.vue"
export default {
  data(){
    return{
      index:0
    }
  },
  name: 'App',
  components:{Car}
}
</script>

子组件

<template>
  <div @click="$emit('input',value+1)">汽车</div>
</template>
<script>
  export default{
    props:["value"]
  }
</script>

父组件通过v-model绑定index到子组件上,而通过v-model绑定的数据在子组件中默认的key是value,所以在props上用value取值,最后通过点击事件执行$emit,而$emit上触发的事件是input,前面我们说过v-model绑定的事件是input,从而在子组件上触发了父组件的input事件,而在触发事件的时候可以传值,所以就实现了父子组件数据双向绑定,如果用的是v-bind,还需要自己去定义事情,所以使用v-model可以减少代码量。


补充,目前sync修饰符一样可以实现双向绑定,在原理上和v-model相差无几

官方文档

<comp :foo.sync="bar"></comp>

会被扩展为:

<comp :foo="bar" @update:foo="val => bar = val"></comp>

只要在子组件用emit触发 updata:foo事件,就可以达到通信的目的


补充2:

默认情况下,v-model会被绑定value,但是某些情况下,value属性会被其他所使用,所以为了避免冲突,可以在在子组件中用model属性来定义v-model绑定的属性和事件,例子


props:["checked"],
model:{
  prop: 'checked',
  event: 'change'
}
以上代码就更改了v-model的默认绑定,取值可以用checked,而触发事件可以触发change事件。
Logo

前往低代码交流专区

更多推荐