vue组件通信,传值方法梳理
1. props ( 父=>子 )
步骤:
- 创建父子组件
- 在子组件组件中添加props属性,值可以是数组或者对象形式
- 父组件给子组件传值
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.father{
width: 300px;
height: 200px;
background-color: aqua;
}
.son{
width: 200px;
height: 100px;
background-color: brown;
}
</style>
</head>
<body>
<div id="app">
<Father class="father"></Father>
</div>
<!-- 父组件 -->
<template id="father">
<div>
<p>父组件中的msg : {{ msg }}</p>
<Son class="son" :txt="msg"></Son>
</div>
</template>
<!-- 子组件 -->
<template id="son">
<div>
<p>子得到的值 :{{ txt }}</p>
</div>
</template>
</body>
</html>
<script src="./lib//vue.js"></script>
<script>
// 创建实例
var vm = new Vue({
el: '#app',
data:{},
methods: {},
components: {
Father:{
template:'#father',
data(){
return{
msg:'父组件需要传给子组件的msg',
}
},
components:{
Son:{
template:'#son',
data(){
return{
byFather:this.txt ,
}
},
props:{
txt:{
type:[Number,String],
}
}
}
}
}
}
})
</script>
2. $emit ( 子 => 父 )
步骤:
- 编写父子组件
- 在子组件模板中编写给父组件传值的按钮 绑定点击事件
- 编写子组件中传值的方法
- 在父组件调用子组件的位置,监听自定义事件
- 编写监听事件对应的方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.father{
width: 300px;
height: 200px;
background-color: aqua;
}
.son{
width: 200px;
height: 100px;
background-color: brown;
}
</style>
</head>
<body>
<div id="app">
<Father class="father"></Father>
</div>
<!-- 父组件 -->
<template id="father">
<div>
<p>父组件接收子的值 : {{ msg }}</p>
<Son class="son" @to_father="acceptSon"></Son>
</div>
</template>
<!-- 子组件 -->
<template id="son">
<div>
<button @click="giveFather">{{ txt }}</button>
</div>
</template>
</body>
</html>
<script src="./lib//vue.js"></script>
<script>
// 创建实例
var vm = new Vue({
el: '#app',
data:{},
methods: {},
components: {
Father:{
template:'#father',
data(){
return{
msg:''
}
},
methods:{
acceptSon(v){
console.log(v);
this.msg = v
}
},
components:{
Son:{
template:'#son',
data(){
return{
txt:'子组件需要传给父组件的msg',
}
},
methods:{
giveFather(){
this.$emit('to_father',this.txt)
}
}
}
}
}
}
})
</script>
3. refs ( 子 => 父 )
- ref 加在普通的元素上,用this.$refs.ref值 , 获取到的是dom元素。
- ref 加在子组件上,用this.$refs.ref值 , 获取到的是组件实例,可以使用组件的所有方法、属性。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.father{
width: 300px;
height: 200px;
background-color: aqua;
}
.son{
width: 200px;
height: 100px;
background-color: brown;
}
</style>
</head>
<body>
<div id="app">
<Father class="father"></Father>
</div>
<!-- 父组件 -->
<template id="father">
<div>
<p>父获取到的值:{{msg}}</p>
<button @click="getRef">借助ref获取子的值</button>
<Son ref="son" class="son"></Son>
</div>
</template>
<!-- 子组件 -->
<template id="son">
<div>
<p>子=>父: {{ gift }}</p>
</div>
</template>
</body>
</html>
<script src="./lib//vue.js"></script>
<script>
// 创建实例
var vm = new Vue({
el: '#app',
data:{},
methods: {},
components: {
Father:{
template:'#father',
data(){
return{
msg:''
}
},
methods:{
getRef(){
console.log(this.$refs);
console.log(this.$refs.son.gift); //茅台
this.msg = this.$refs.son.gift;
}
},
components:{
Son:{
template:'#son',
data(){
return{
gift:'茅台'
}
},
methods:{ }
}
}
}
}
})
</script>
4.$parent ( 父 => 子 )
this.$parent,可以获取到当前组件的父组件实例,即,可以直接调用使用父组件内的方法、属性、一切。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.father{
width: 300px;
height: 200px;
background-color: aqua;
}
.son{
width: 200px;
height: 100px;
background-color: brown;
}
</style>
</head>
<body>
<div id="app">
<Father class="father"></Father>
</div>
<!-- 父组件 -->
<template id="father">
<div>
<p >父=>子 的值: {{msg}}</p>
<Son class="son"></Son>
</div>
</template>
<!-- 子组件 -->
<template id="son">
<div>
<button @click="getParent">借助$parent获取父组件的值</button>
<p>子组件获取到的值: {{ txt }}</p>
</div>
</template>
</body>
</html>
<script src="./lib//vue.js"></script>
<script>
// 创建实例
var vm = new Vue({
el: '#app',
data:{},
methods: {},
components: {
Father:{
template:'#father',
data(){
return{
msg:'父组件的值'
}
},
methods:{ },
components:{
Son:{
template:'#son',
data(){
return{
txt:''
}
},
methods:{
getParent(){
console.log(this.$parent);
console.log(this.$parent.msg); //父组件的值
this.txt = this.$parent.msg;
}
}
}
}
}
}
})
</script>
5. $children ( 子 => 父 )
vm.$children可以获取到所有的子组件以数组形式展现,可以通过下标获取对应组件的实例属性方法。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.father{
width: 300px;
height: 200px;
background-color: aqua;
}
.son{
width: 200px;
height: 100px;
background-color: brown;
}
</style>
</head>
<body>
<div id="app">
<Father class="father"></Father>
</div>
<!-- 父组件 -->
<template id="father">
<div>
<p >父获取到的值: {{msg}}</p>
<button @click="getSon">借助$children获取子组件的值</button>
<Son class="son"></Son>
</div>
</template>
<!-- 子组件 -->
<template id="son">
<div>
<p>子=>父 的值: {{ gift }}</p>
</div>
</template>
</body>
</html>
<script src="./lib//vue.js"></script>
<script>
// 创建实例
var vm = new Vue({
el: '#app',
data:{},
methods: {},
components: {
Father:{
template:'#father',
data(){
return{
msg:''
}
},
methods:{
getSon(){
console.log(this.$children);
this.msg = this.$children[0].gift;
}
},
components:{
Son:{
template:'#son',
data(){
return{
gift:'青花'
}
},
methods:{ }
}
}
}
}
})
</script>
6. slot 插槽 ( 另外再具体介绍)
匿名插槽:
具名插槽: (vue2.6以后插入具名插槽)
7.$attrs:爷孙传值
步骤:
- 爷爷组件把想要传递给孙子组件的值,通过自定义属性值的方式,即传统的正向传值方式,传递给父组件
- 父组件可以通过props接受父组件想要的数据,父组件中没有使用props接受的值,可以通过$attrs传递给孙子组件
- a t t r s 添加在父组件模板调用孙子组件的位置,给孙子组件添加 ‘ v − b i n d = ′ attrs添加在父组件模板调用孙子组件的位置,给孙子组件添加`v-bind=' attrs添加在父组件模板调用孙子组件的位置,给孙子组件添加‘v−bind=′attrs’`,
- 孙子组件在自己的组件中,使用props,接收爷爷组件传递给父组件的值,(父组件没有用pros接收的值)
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.grandfa{
width: 500px;
height: 400px;
background-color: rgb(246, 255, 0);
}
.father{
width: 450px;
height: 240px;
background-color: aqua;
}
.son{
width: 400px;
height: 100px;
background-color: rgb(243, 95, 95);
}
</style>
</head>
<body>
<div id="app">
<Grandfa class="grandfa"></Grandfa>
</div>
<!-- 爷爷组件 -->
<template id="grandfa">
<div>
<h1>爷爷组件</h1>
<p>爷爷 => 孙子:{{msg0}},{{msg1}}</p>
<!-- 注意 givevals1: 不可用驼峰命名法(giveVals1:报错),可保持小写或用下划线give_vals1-->
<Father :givevals1="msg0" :givevals2="msg1"></Father>
</div>
</template>
<!-- 父组件 -->
<template id="father">
<div class="father">
<h1>父组件</h1>
<p>通过props接收的值giveVals1: {{ givevals1 }}</p>
<Son v-bind="$attrs"></Son>
</div>
</template>
<!-- 子组件 -->
<template id="son">
<div class="son">
<h1>孙子组件</h1>
<p>接收爷爷组件的giveVals2:{{ givevals2 }}</p>
</div>
</template>
</body>
</html>
<script src="./lib//vue(1).js"></script>
<script>
// 创建实例
var vm = new Vue({
el: '#app',
data:{},
methods: {},
components: {
Grandfa:{
template:'#grandfa',
data(){
return{
msg0: '祖母绿',
msg1: '珍珠'
}
},
methods:{ },
components:{
Father:{
template:'#father',
props:{
givevals1:{
type: String
}
},
data(){
return{}
},
methods:{ },
components:{
Son:{
template:'#son',
props:{
givevals2:{
type: String
}
},
data(){
return{}
},
methods:{}
}
}
}
}
}
}
})
</script>
8.$listeners: 孙子传值爷爷
步骤:
- 孙子组件自定义事件传值,传给上级组件
- 在父组件中 ,给调用孙子组件的位置 添加
v-on="$listeners"
- 爷爷组件中,在调用父亲组件的位置,监听孙子组件的自定义事件,取值
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.grandfa{
width: 500px;
height: 400px;
background-color: rgb(246, 255, 0);
}
.father{
width: 480px;
height: 240px;
background-color: aqua;
}
.son{
width: 450px;
height: 100px;
background-color: rgb(243, 95, 95);
}
</style>
</head>
<body>
<div id="app">
<Grandfa class="grandfa"></Grandfa>
</div>
<!-- 爷爷组件 -->
<template id="grandfa">
<div>
<h1>爷爷组件</h1>
<p>爷爷获取孙子的值:{{msg}}</p>
<Father @to_grandfa="accept_son"></Father>
</div>
</template>
<!-- 父组件 -->
<template id="father">
<div class="father">
<h1>父组件</h1>
<Son v-on="$listeners"></Son>
</div>
</template>
<!-- 子组件 -->
<template id="son">
<div class="son">
<h1>孙子组件</h1>
<p>孙子=>爷爷的值:{{ obj }}</p>
<button @click="change">传值给爷爷</button>
</div>
</template>
</body>
</html>
<script src="./lib//vue(1).js"></script>
<script>
// 创建实例
var vm = new Vue({
el: '#app',
data:{},
methods: {},
components: {
Grandfa:{
template:'#grandfa',
data(){
return{
msg:{}
}
},
methods:{
accept_son(v){
this.msg = v;
}
},
components:{
Father:{
template:'#father',
props:{},
data(){
return{}
},
methods:{ },
components:{
Son:{
template:'#son',
props:{
},
data(){
return{
obj:{
gift1:'养生茶',
gift2:'太极拳谱'
}
}
},
methods:{
change(){
this.$emit('to_grandfa',this.obj)
}
}
}
}
}
}
}
}
})
</script>
9. bus传值 (※)
使用方法:(适用于 多层组件传值)
1、在main.js中全局挂载bus
2、在要传值的组件中,使用this.bus.
e
m
i
t
(
′
自定义事
件
′
,要传递的值
)
3
、在需要接收传值的组件中,
m
o
u
n
t
e
d
钩子函数中,使用
t
h
i
s
.
b
u
s
.
emit('自定义事件',要传递的值) 3、在需要接收传值的组件中,mounted钩子函数中,使用this.bus.
emit(′自定义事件′,要传递的值)3、在需要接收传值的组件中,mounted钩子函数中,使用this.bus.on(‘自定义事件名’,(v)=>{v}) 接受传递的数据
以6层组件嵌套为例:
我们先自定义6个组件完成嵌套:
A.vue
<template>
<div class="abox">
<h1>A组件,最外层的</h1>
<B></B>
</div>
</template>
<script>
import B from "../components/B";
export default {
props: {},
data() {
return {};
},
methods: {},
components: {
B,
},
};
</script>
<style scoped lang="less">
.abox {
width: 100%;
padding: 20px;
background-color: #e6ddcd;
color: white;
}
</style>
B.vue
<template>
<div class="bbox">
<h2>B组件</h2>
<C></C>
</div>
</template>
<script>
import C from "./C";
export default {
props: {},
data() {
return {};
},
methods: {},
components: {
C,
},
};
</script>
<style scoped lang="less">
.bbox {
width: 80%;
margin: 20px auto;
padding: 20px;
color: white;
background-color: #c9b486;
}
</style>
C.vue
<template>
<div class="cbox">
<h3>C组件</h3>
<D></D>
</div>
</template>
<script>
import D from "./D";
export default {
props: {},
data() {
return {};
},
methods: {},
components: {
D,
}
};
</script>
<style scoped lang="less">
.cbox {
width: 80%;
margin: 20px auto;
padding: 20px;
background-color: #2b6363;
}
</style>
D.vue
<template>
<div class="dbox">
<h4>D组件</h4>
<E></E>
<F></F>
</div>
</template>
<script>
import F from "./F";
import E from "./E";
export default {
props: {},
data() {
return {};
},
methods: {},
components: {
F,
E,
},
};
</script>
<style scoped lang="less">
.dbox {
width: 80%;
margin: 20px auto;
padding: 20px;
color: white;
background-color: #153547;
}
</style>
E.vue
<template>
<div class="ebox">
<h5>E组件</h5>
</div>
</template>
<script>
export default {
props: {},
data() {
return {
egift: "E孝敬的茅台",
};
},
methods: {},
components: {},
};
</script>
<style scoped lang="less">
.ebox {
width: 80%;
margin: 20px auto;
padding: 20px;
color: white;
background-color: #071632;
}
</style>
F.vue
<template>
<div class="ebox">
<h5>F组件</h5>
</div>
</template>
<script>
export default {
props: {},
data() {
return {};
},
methods: {},
components: {},
mounted() {
},
};
</script>
<style scoped lang="less">
.ebox {
width: 80%;
margin: 20px auto;
padding: 20px;
color: white;
background-color: #071632;
}
</style>
1、在main.js中全局挂载bus
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
//1、把bus属性 挂载在vue原型对象上
Vue.prototype.bus = new Vue();
new Vue({
router,
render: function (h) { return h(App) }
}).$mount('#app')
2、在需要传递数据的组件中使用bus触发自定义事件
此处以E.vue为例
<template>
<div class="ebox">
<h5>E组件</h5>
<button @click="EChange">E要孝敬大家了</button>
</div>
</template>
<script>
export default {
props: {},
data() {
return {
egift: "E孝敬的茅台",
};
},
methods: {
EChange() {
this.bus.$emit("ESend", this.egift);
},
},
components: {},
};
</script>
<style scoped lang="less">
.ebox {
width: 80%;
margin: 20px auto;
padding: 20px;
color: white;
background-color: #071632;
}
</style>
3、需要接收的组件接收,使用this.bus.$on(‘自定义事件名’,()=>{v})
此处以A.vue组件为例
<template>
<div class="abox">
<h1>A组件,最外层的</h1>
<B></B>
</div>
</template>
<script>
import B from "../components/B";
export default {
props: {},
data() {
return {};
},
methods: {},
components: {
B,
},
mounted() {
this.bus.$on("ESend", (v) => {
console.log("a接收E孝敬的:", v);
});
},
};
</script>
<style scoped lang="less">
.abox {
width: 100%;
padding: 20px;
background-color: #e6ddcd;
color: white;
}
</style>
在c组件,F组件中如法炮制,同样的写法。当我们触发E组件传值时,神奇的现象来了: