!!!这边文章记录的是 vue2 的概念,vue3 对双向绑定进行了改动,不要把一下代码放到 vue3 中运行。vue3 双向绑定的改动参考 这里
序
作者:玄晓乌屋
最后更新时间:2019/6/25
vue 自定义组件双向绑定没有直接一步到位的方式,全都是是通过属性传值和事件传值实现的。v-model
不能直接支持组件的双向绑定。
属性&事件传值双向绑定
这种方式最复杂,也最容易理解,前提是需要深刻理解事件传值和属性传值。
新建一个组件 Com.vue :
<template>
<!-- 单项绑定props值到value -->
<!-- 监听input事件,提交组件事件myInput并传递更新的值 -->
<input :value="query" @input="$emit('myInput',$event.target.value)">
</template>
<script>
export default {
// 获取props值
props: ['query']
}
</script>
新建一个 .vue
文件引入 Com.vue 组件并调用:
<template>
<div id="home">
<!-- 传递query给Com组件,并设置myInput事件更新当前组件的query -->
<Com :query="query" @myInput="val => query=val"/>
{{query}}
</div>
</template>
<script>
import Com from '../components/Com'
export default {
components: { Com },
data() {
return {
query: null
}
}
}
</script>
解释:
这种通过事件和组件传值的方式并不难,就是在父组件中传值给子组件,并设置一个事件。
子组件获取到值后先单项绑定到某个地方,上面绑到了 input
元素中,在 input
元素中通过监听 input
事件来提交组件事件 myInput
。如果学过 react ,这就是简单的状态提升。
总结:属性&事件传值双向绑定可控性很好,支持多个数据的双向绑定,但是复杂和凌乱,单个数据可以使用,但是多个数据会造成代码可读性很低,不实用。
v-model组件双向绑定
官方对v-model
指令做了一些准备工作,和上述 属性&事件传值的双向绑定 相比:
v-model
默认传递一个名为 value
的值和默认绑定一个名为input
的事件更新这个值。
注意:使用v-model
时,默认属性和事件名是固定的value
和input
。
如下:
<template>
<div id="home">
<Com v-model="query"/>
<Com :value="query" @input="v => query=v"/>
<!-- 上面两行等价 -->
{{query}}
</div>
</template>
实现:
修改 Com.vue 文件如下:
<template>
<!-- 单项绑定value -->
<!-- 监听input事件提交组件事件input,注意这两个input不一样了,前一个是<input/>元素的事件,后一个是组件的事件 -->
<input :value="value" @input="$emit('input',$event.target.value)">
</template>
<script>
export default {
// 这个值改成value
props: ['value']
}
</script>
新建任意 .vue
文件引入 Com.vue 组件:
<template>
<div id="home">
<Com v-model="query"/>
<Com :value="query" @input="v => query=v"/>
<!-- 上面两行等价 -->
{{query}}
</div>
</template>
<script>
import Com from '../components/Com'
export default {
components: { Com },
data() {
return {
query: null
}
}
}
</script>
此时在页面上有两个input
框,两边的值都绑定同一个值query
。
如图:
总结:v-model
虽然简化了 属性&事件传值双向绑定 的模式,但是只能传一个值,并且传递固定属性 value
和固定触发事件input
,只适用于传单个值的组件,比如常见的表单组件。
.sync修饰符双向绑定
.sync
修饰符简化了 属性&事件传值的双向绑定 的模式,虽然比v-model
的方式稍微麻烦点,但是支持多个数据在组件上双向绑定。
使用.sync
修饰符修饰一个单项绑定到组件的属性,会默认绑定一个update:myPropName
的事件,myPropName
是绑定的属性名。
修改 Com.vue 组件如下:
<template>
<!-- 监听input事件,提交.sync修饰符提供的update:<myPropName>事件 -->
<input :value="value" @input="$emit('update:value',$event.target.value)">
</template>
<script>
export default {
props: ['value']
}
</script>
新建一个 .vue
文件引入 Com.vue 并使用:
<template>
<div id="home">
<Com :value.sync="query"/>
{{query}}
</div>
</template>
<script>
import Com from '../components/Com'
export default {
components: { Com },
data() {
return {
query: null
}
}
}
</script>
上述方式依旧可以实现双向数据绑定。
总结:实用简单,代码可读性较好,可控性好,可以支持多个数据的双向数据绑定。
总结
以上提供3种方式,属性&事件传值双向绑定比较复杂,但是逻辑清晰,是组件双向数据绑定的核心。v-model组件双向绑定简单,适用于单个数据。.sync修饰符双向绑定可控性好,适用于多个属性双向绑定。