1. v-model 的原理
我们在 vue 项目中主要使用 v-model
指令在表单 <input>
、<textarea>
及 <select> 元素上创建双向数据绑定,我们知道 v-model
本质上不过是语法糖,v-model
在内部为不同的输入元素使用不同的属性并抛出不同的事件:
-
<text>
和<textarea>
元素使用value
属性和input
事件; -
checkbox
和radio
使用checked
属性和change
事件; -
select
字段将value
作为prop
并将change
作为事件。
2. 在组件上使用 v-model
使用v-model
,可以很方便地在子组件中同步父组件的数据
一个组件上的 v-model
默认会利用名为 value
的 prop
和名为 input
的事件。也就是说组件只要提供一个名为 value
的 prop
,以及名为 input
的自定义事件,满足这两个条件,使用者就能在自定义组件上使用v-model
- 简单使用,父子组件相互传值
// 子组件 C.vue
<template>
<div>
<button @click="change">click</button>
{{ value }}---->父组件传过来的值
</div>
</template>
<script>
export default {
props: {
value: String //定义value属性
}
methods:{
change(){
this.$emit('input','change--from son')
}
}
};
</script>
// 父组件 App.vue
<template>
<div id="app">
<C v-model="msg"></C>
<div> {{ msg }} </div>
</template>
- 接受并改变父组件传递过来的
value
初始值,实现功能,每点击click +100
按钮一次,父组件中的total
加100
// 子组件 C.vue
<template>
<div>
<button @click="change">click +100</button>
</template>
<script>
export default {
props:{
value: Number
},
data(){
return {
count:this.value // copy 父组件传来的 value 值
}
},
methods:{
change(){
this.count += 100
this.$emit('input',this.count)
}
}
};
</script>
//App.vue 父组件
<template>
<div id="app">
<C v-model="total"></C>
<div>{{total}}</div>
</div>
</template>
<script>
import C from './components/C'
export default {
components: {C},
data(){
return {
total: 0 , // 可以给 total 设置一个初始值,三个 total 都为同一个
}
},
}
</script>
- 定制
v-model
指令的prop
和event
名称
一个组件上的v-model
默认会利用名为value
的 prop 和名为input
的事件,但是像单选框、复选框等类型的输入控件可能会将value
特性用于不同的目的。model
选项可以用来避免这样的冲突:
export default {
model: {
prop: 'value',
event: 'input'
},
// ...
}
// 定制 v-model , 改写 2 中的子组件
// C.vue
<template>
<div>
<button @click="change">click +100</button>
</template>
<script>
export default {
model: {
prop: "msg", //这个字段,是指父组件设置 v-model 时,将变量值传给子组件的 msg
event: "changing" //这个字段,是指父组件监听 parent-event 事件
},
props:{
msg: Number // 此处必须定义和 model 的 prop 相同的 props,因为 v-model 会传值给子组件
},
data(){
return {
count:this.msg // value 变成 msg
}
},
methods:{
change(){
this.count += 100
this.$emit('changing',this.count)
}
}
};
</script>
网友评论