在这之前我们已经学习过了组件的属性,它可以用于组件的传值,将父组件的数据传给子组件。但是它只能实现单向的组件传值,还不能实现子传父。
在此基础上,我们今天来研究组件之间的反向传值。
这里我介绍三种组件中反向传值的方法:
一、利用this.$emit()函数实现
实现原理:有时候我们子组件的data 数据需要交给父组件使用: 通过在子组件上定义自定义事件,在子组件中通过$emit 来触发事件;子组件的事件被触发并传参,事件处理函数可以接收到子组件的数据;事件绑定的事件处理函数在父节点上,故可在事件处理函数中用到子组件的数据值来修改父节点的数据。
1、首先创建Box1.vue文件,配置子组件,并创建好自定义事件。
<template>
<div class="box1">
<button @click="fn">修改属性title</button>
</div>
</template>
<script>
export default{
data() {
return {
msg:"修改后的msg值"
}
},
methods: {
fn(){
//当点击按钮后,我们自定义的事件触发并将当前组件的msg传到父组件中绑定的监听函数
this.$emit("updatemsg",this.msg)
}
},
}
</script>
<style>
.box1{
width: 150px;
height: 150px;
background-color: aqua;
}
</style>
2、创建App.vue文件,配置父组件,导入注册使用Box1组件,在Box1标签中绑定我们的自定义事件updatemsg,绑定的函数接收子组件传来的值。
<template>
<div class="app">
<h1>app父组件</h1>
<div>{{this.msg}}</div>
<Box1 @updatemsg="fm"></Box1>
</div>
</template>
<script>
import Box1 from "@/components/box1.vue"
export default {
data() {
return {
msg:"父组件的数据"
}
},
components:{
Box1
},
methods: {
fm(arg){
this.msg=arg
}
},
}
</script>
<style>
.app{
width: 300px;
height: 300px;
background-color: aquamarine;
}
</style>
当我们点击按钮以后,父组件的msg的值改为子组件传来的值,对应页面从新渲染。
效果:
初始页面:
点击后:
即子组件向父组件传值成功。
二、利用this.$emit()函数和.sync实现
这一种可以说是第一种的优化,当对于子组件有属性时,我们父组件再给子组件传值时只需要在属性名后.sync就不用再给该子组件绑定自定义事件,对应子组件中this.$emit("update:属性名",传入参数),过后系统会自动帮我们处理。
缺点:只能用在子组件有属性时,只能改变传入属性的值。
改进上面的代码:
子组件中添加属性,改动this.$emit()
<template>
<div class="box1">
<!-- 等待父组件传title属性的值 -->
<div>{{title}}</div>
<button @click="fn">修改属性title</button>
</div>
</template>
<script>
export default{
//创建属性
props:["title"],
data() {
return {
msg:"修改后的msg值"
}
},
methods: {
fn(){
this.$emit("update:title",this.msg)
}
},
}
</script>
<style>
.box1{
width: 150px;
height: 150px;
background-color: aqua;
}
</style>
父组件:
<template>
<div class="app">
<h1>app父组件</h1>
<div>{{this.msg}}</div>
<Box1 :title.sync="msg"></Box1>
</div>
</template>
<script>
import Box1 from "@/components/box1.vue"
export default {
data() {
return {
msg:"父组件的数据"
}
},
components:{
Box1
},
}
</script>
<style>
.app{
width: 300px;
height: 300px;
background-color: aquamarine;
}
</style>
三、利用v-model和this.$emit()函数传值
v-model前面在双向数据绑定我们已经学习过了,其实它也可以将其用在组件上。
v-model本质是一种语法糖,解析为:value和@input。
了解完本质后,我想大家应该知道如何实现了。首先我们需要在子组件中定义一个value属性,我们在v-model="传值"时,就相当于给子组件的value属性传值。然后我们还需要在this.$emit("input","参数")中如下操作,当触发this.$emit时,参数就会传给父组件传值的那个属性。
父组件代码:
<template>
<div class="app">
<h1>app父组件</h1>
<div>{{this.msg}}</div>
<Box1 v-model="msg"></Box1>
</div>
</template>
<script>
import Box1 from "@/components/box1.vue"
export default {
data() {
return {
msg:"父组件的数据"
}
},
components:{
Box1
},
}
</script>
<style>
.app{
width: 300px;
height: 300px;
background-color: aquamarine;
}
</style>
子组件代码:
<template>
<div class="box1">
<!-- 等待父组件传title属性的值 -->
<div>{{value}}</div>
<button @click="fn">修改属性msg</button>
</div>
</template>
<script>
export default{
//创建属性
props:["value"],
data() {
return {
msg:"修改后的msg值"
}
},
methods: {
fn(){
this.$emit("input",this.msg)
}
},
}
</script>
<style>
.box1{
width: 150px;
height: 150px;
background-color: aqua;
}
</style>