VUE-父子组件通信 及 v-model实现通信
一、父组件向子组件传值
1、首先创建父组件(parent)和子组件(child),并在父组件中注册子组件
2、在父组件调用子组件标签中添加一个自定义属性(msg)
// 父组件
<template>
<div class="parent">
<Child :msg="parentMsg"></Child>
</div>
</template>
<script>
import Child from './child.vue';
export default {
data() {
return {
parentMsg: "我是传给子组件的值"
};
},
components: {
Child
},
}
</script>
3、在子组件的props
中将父组件中自定义属性(msg)添加进去,则该属性在子组件中可以像data中定义的属性一样使用
// 子组件
<template>
<div class="child">
<p>{{ msg }}</p>
</div>
</template>
<script>
export default {
props: {
msg:{
type:String,
default:""
}
}
}
</script>
二、子组件向父组件传值
1、在子组件中创建一个按钮,给按钮绑定一个点击事件
2、在响应 点击事件的函数中使用$emit
来发送一个自定义事件(listenChildEvent)给父组件,并传递一个参数
<template>
<div class="child">
<p>{{ msg }}</p>
<button @click="sendMsg">向父组件传值</button>
</div>
</template>
<script>
export default {
props: {
msg:{
type:String,
default:""
}
},
methods:{
sendMsg(){
this.$emit("listenChildEvent","this message is from child");
}
}
}
</script>
3、在父组件调用子组件标签中,监听该自定义事件(listenChildEvent)并添加一个响应该事件的处理方法,并接收子组件传过来的数据
<template>
<div class="parent">
<Child :msg="parentMsg" @listenChildEvent="acceptMsgFromChild"></Child>
</div>
</template>
<script>
import Child from './child.vue';
export default {
data() {
return {
parentMsg: "我是传给子组件的值"
};
},
components: {
Child
},
methods:{
acceptMsgFromChild(data){
console.log(data);//或者将接受值处理
}
}
}
</script>
三、使用v-model实现父子组件通信
1、v-model
一般用于表单的双向数据绑定
<template>
<div>
<input type="text"
v-model="msg">
<p>{{msg}}</p>
</div>
</template>
<script>
export default {
data () {
return {
msg: ''
}
}
}
</script>
2、v-model原理
由此看出,v-model是v-bind
和v-on:input
的结合,即监听了表单的input事件,然后修改value属性对应的值
<template>
<div>
<input type="text"
:value="msg"
@input="bind">
<p>{{msg}}</p>
</div>
</template>
<script>
export default {
data () {
return {
msg: ''
}
},
methods: {
bind () {
this.msg = event.target.value
}
}
}
</script>
3、v-model
除了在输入表单上可以使用之外,在组件上也可以使用,以实现父子组件的双向数据绑定
// -------------------------------父组件
<template>
<div>
<!-- 在父组件中用v-model相当于,v-bind绑定了value,以及执行了v-on:input事件 -->
<child v-model="flag"></child>
<div>{{flag}}</div>
</div>
</template>
<script>
export default {
data () {
return {
flag: ''
}
},
components: {
child
}
}
</script>
// -------------------------------子组件
<template>
<div>
<div class="btn" @click="confirm">确定</div>
</div>
</template>
<script>
export default {
// 用props接收父组件传递的value值,从而实现双向数据绑定
props: {
value: {
type: Boolean,
default: true
}
},
methods: {
// 通过$emit触发父组件的input事件,并将第二个参数作为值传递给父组件
confirm () {
this.$emit('input', false)
}
}
}
</script>
最后,父组件中的flag默认为true,点击了子组件中的“确定”后,子组件将false传递给了父组件的flag
4、v-model添加model
选项
以上这种方式实现的父子组件的v-model通信,限制了popos接收的属性名必须为value和emit触发的必须为input,这样容易有冲突,特别是在表单里面。所以,为了更优雅的使用v-model通信,可以在子组件中使用model
选项
// 子组件
<template>
<div>
<div class="btn" @click="confirm">确定</div>
</div>
</template>
<script>
export default {
// model选项用来避免冲突,prop属性用来指定props属性中的哪个值用来接收父组件v-model传递的值,例如:这里用props中的flag1来接收父组件传递的v-model值;event属性可以理解为父组件@input的别名,从而避免冲突,即emit时要提交的事件名。
model: {
prop: 'flag1',
event: 'changed'
}
// 用props接收父组件传递的value值,从而实现双向数据绑定
props: {
value: {
type: Boolean,
default: true
}
},
methods: {
// 通过$emit触发父组件的input事件,并将第二个参数作为值传递给父组件
confirm () {
this.$emit('input', false)
}
}
}
</script>
5、v-model实现动态传值
<template>
<div>
<new-input v-model="name"></new-input>{{name}}
</div>
</template>
<script>
import Vue from 'vue'
Vue.component('new-input', {
props: {
value: {
type: String
}
},
template: '<label><input type="text" v-model="newValue" /> 你的名字:</label>',
computed: {
newValue: {
get: function () {
return this.value
},
set: function (value) {
this.$emit('input', value)
}
}
}
})
export default {
data () {
return {
name: 'nick'
}
}
}
</script>