使用情景:一般情况下我们使用一个组件,可以通过prop给这个组件传值,组件可以使用emit来改变使用者的数据。如果频繁修改同一个数据,那么可以使用v-model进行父子组件数据的双向绑定。常用于处理输入的文本编辑组件。
下面的html代码复制到一个文件中运行即可显示效果
一、使用prop和emit实现双向绑定
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>子父组件双向绑定</title>
</head>
<body>
<div id="root"></div>
<script type="text/javascript">
const compoent = {
props: {
value: String
},
methods:{
handleChange(e) {
//使用事件监听机制将事件发布出去,由父组件监听并获取
this.$emit('input', e.target.value);
}
},
template: `
<div>
子组件中的值:<input :value="value" @input="handleChange"></input>
</div>`,
}
var app = new Vue({
el:'#root',
data(){
return{
value:''
}
},
components:{
CompOne: compoent //注册组件
},
template:`
<div>
父组件中的值:<input v-model='value'></input>
<comp-one :value="value" @input="value = arguments[0]">
</comp-one>
</div>`
});
</script>
</body>
</html>
二、使用v-model实现双向绑定
事实上,上面的prop和emit已经实现了v-model的功能,下面的方式等效:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>子父组件双向绑定</title>
</head>
<body>
<div id="root"></div>
<script type="text/javascript">
const compoent = {
props: {
value: String
},
methods:{
handleChange(e) {
this.$emit('input', e.target.value);
}
},
template: `
<div>
子组件中的值:<input :value="value" @input="handleChange"></input>
</div>`,
}
var app = new Vue({
el:'#root',
data(){
return{
value:''
}
},
components:{
CompOne: compoent //注册组件
},
template:`
<div>
父组件中的值:<input v-model='value'></input>
<comp-one v-model="value"></comp-one>
</div>`
});
</script>
</body>
</html>
三、父子组件双向绑定的通用版本
至此,父子组件数组双向绑定功能已经实现,以后写组件的时候需要相互传数据的时候就可以这样使用了。但是上面的写法限定了我们父子组件的数据必须使用同一个变量,名字需要一致,因此需要改进,给子组件加上一个model属性:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>子父组件双向绑定</title>
</head>
<body>
<div id="root"></div>
<script type="text/javascript">
const compoent = {
model: {
prop: 'value1',
event: 'change'
},
props: ['value1'],
methods:{
handleChange(e) {
this.$emit('change', e.target.value);
}
},
template: `
<div>
子组件中的值:<input :value="value1" @input="handleChange"></input>
</div>`,
}
var app = new Vue({
el:'#root',
data(){
return{
value:''
}
},
components:{
CompOne: compoent
},
template:`
<div>
父组件中的值:<input v-model='value'></input>
<comp-one v-model="value"></comp-one>
</div>`
});
</script>
</body>
</html>