v-model 解析 和 自定义 v-model
$emmit和 $v-onvue 组件之间数据绑定是基于单项绑定的,想要父子组件之间的数据和行为的交互要使用 $emit和 $v-on。<!-- child component --><template><dev @click='handleClik'> {{valu
$emit 和 $v-on
vue 组件之间数据绑定是基于单项绑定的,想要父子组件之间的数据和行为的交互要使用 $emit
和 $v-on
。
<!-- child component -->
<template>
<dev @click='handleClik'> {{value}} </dev>
</template>
<script>
export default {
name: 'child',
props: ['value'],
methods:{
handleClik(){
this.$emit('change', 'value1')
}
}
}
</script>
<template>
<child @change="onChange" :vlaue='val'/>
</template>
<script>
import Child from './child'
export default {
name: 'child',
components: {Child},
methods:{
onChange(val){
this.value = val
}
}
}
</script>
child 组件内部内部的 value 是根据父级传入的 value 显示的, 如果想要改变 value 的值,在child 组件里面是不行,只能通过 $emit
向父级传入想要改变的值,然后 父级在捕获到 change
时间的时候,拿到 child 组件传来的值, 再次给 value 赋值 this.value = val
。
这种方式是组件与组件数据和事件交互的惯常用法,最然逻辑是很明了的,但是如果遇到复杂的组件间交互逻辑写起来就会比较繁琐。
v-model
还有一种数据的交互方式是使用 v-model
, 这种方法专门是 input 组件, 这只不过是 一种语法糖的形式:
input
组件上面本身有一个 onInput
事件。每当素输入框内容发生发生的时候,就会触发这个事件,然后把 input 的值 通过 $emit
传递出去。
<!-- 下面两个表达 实现同样的效果 -->
<input v-model='val'>
<input :value='val' @input="val = $event.target.value"/>
这里需要注意的是
v-model
默认情况下只会接受value
属性和响应input
事件。 因为v-model
本身是基于input
框定制的,value
是 input 内部定制的绑定值的属性,input
方法是内部定制的当值改变出发的事件。
了解了 v-model
的语法, 可以根据这种写法自定义 组件的 v-model
;
还是使用开头的 child 组件的例子;
<!-- child component -->
<template>
<dev @click='handleClik'> {{value}} </dev>
</template>
<script>
export default {
name: 'child',
props: ['value'],
methods:{
handleClik(){
this.$emit('input', 'value1')
}
}
}
</script>
<template>
<child :vlaue='val' @input='val = $event'/>
<!-- 等同于 -->
<child v-model='val'/>
</template>
<script>
import Child from './child'
export default {
name: 'child',
components: {Child}
}
</script>
定制 v-model
上面说 v-model 只能接受 value
属性和响应 input
事件,其实这种说法并不是绝对的,我们可以通过 model
选项来改变这种情况。
model
接受有两个属性:
- props 代替原来
value
的值。 - event 代替原本
input
出发的事件。
子组件
<template>
<div v-if="show">
<div>
<p>定制 v-model</p>
<button @click='close'>关闭组件</button>
</div>
</div>
</template>
<script>
export default {
model: {
prop: 'show',
event: 'close'
},
props: ['show'],
methods: {
close () {
this.$emit('close',false)
}
}
}
</script>
父组件
<template>
<div>
<button @click="show=true">打开model</button>
<child v-model="show" ></child>
<!-- 等同于 -->
<child :show='show' @close="show = $event"></child>
</div>
</template>
<script>
import Child from './child'
export default {
components: {
Child
},
data () {
return {
show: false
}
}
}
</script>
上面的例子通过在子组件内部定义 model
选项来改变 v-model
绑定属性和响应的方法,
- 当父组件点击
打开model
按钮的时候,内部的show
属性变为了true
, 这时因为子组件的显示与隐藏是根据props
里面的show
来确定的, 子组件将会显示。 - 点击子组件的
关闭组件
按钮, 出发了close
事件,这个事件中将会像父级暴露一个close
方法,并传递一个false
参数。 - 父级触发
close
方法,改变show
的值.
这个过程在使用 $emit
和 v-on
时的逻辑,因为我们自定义了 model
属性, 这时就可以在使用 child
组件的时候就可以使用 v-model
来简写这种写法啦。
更多推荐
所有评论(0)