分两种:
1)父子如何通信
2)非父子之间如何通信
为什么要通信,因为每组件中的data只能在当前使用,所以要用一些通信手段 。
一.父组件向子组件传递数据
1.语法
父
子
2.props验证
props的值为{}时,可以做props验证.
type(类型) :props做校验时的常见类型:String,Number,Array,Object,Function,Boolean
required(必填项)
validator(验证器)
default(默认值)
父
子
二. 子组件向父组件传递数据
子传父: 必须触发事件 子组件:通过触发$emit来触发自定义事件 父组件:通过触发自定义事件来接收数据 注意: 父组件中通过触发自定义事件时,传递的参数需要通过$event来传递,但是$event可以省略
1.语法
父
子
2.子传父应用
用户和你的网站进行交互了,会用的多一点。加入购物车/登录/注册
<template>
<div class="box">
<h4>子传父应用</h4>
<!-- <div class="mask" v-if="isShow">
<span>登录成功</span>
</div> -->
<v-toast
v-if="isShow"
@hide="isShow=false"
:msg="msg"
></v-toast>
<div class="box">
<h5>登录</h5>
<!-- <button @click="isShow = true">登录按钮</button> -->
<button @click="login">登录按钮</button>
</div>
<div class="box">
<h5>注册</h5>
<!-- <button @click="isShow = true">注册按钮</button> -->
<button @click="register">注册按钮</button>
</div>
<div class="box">
<h5>加入购物车</h5>
<button>加入购物车按钮</button>
</div>
</div>
</template>
<script>
import vToast from './Toast.vue'
export default {
data(){
return {
isShow:false,
msg:'加入购物车成功'
}
},
components:{
vToast
},
mounted(){
},
methods:{
login(){
console.log( 'login' );
this.isShow = true
this.msg = '登录失败'
},
register(){
console.log( 'register' );
this.msg = '注册成功'
this.isShow = true
}
}
}
</script>
子
<template>
<div>
<!-- 一个弹框组件 -->
<div class="mask">
<span>{{msg}}</span>
</div>
</div>
</template>
<script>
export default {
props:[ 'msg' ],
mounted(){
//console.log( 'toast弹框挂载成功了,并开启了一个定时器' );
setTimeout(()=>{ //箭头函数中的this是上层环境
console.log( '我要把show改成false' );
this.$emit( 'hide' )
},2000)
}
}
</script>
<style scoped>
.mask{
width: 100vw;
height: 100vh;
position: absolute;
top:0;
left: 0;
}
.mask span{
display: inline-block;
position:absolute;
top: 50%;
left: 50%;
transform: translate(-50% -50%);
background-color: rgba(0,0,0,0.6);
color: #fff;
padding: 10px 20px;
border-radius: 20px;
}
</style>
3.父传子总结
父传子,父组件传递数据给子组件,默认是父变,子变;子变,父不变,还报错
直接修改:父变,子变,子变,父变,还不报错 ,传递对象。因为本质上对象是引用类型
间接修改:子组件想要修改父组件的值,使用子传父。$emit
父
<template>
<div class="box">
<h4>父传子,子传父总结</h4>
<!--
父传子,父组件传递数据给子组件,默认是父变,子变;子变,父不变,还报错
直接修改:父变,子变,子变,父变,还不报错 ,传递对象。因为本质上对象是引用类型
间接修改:子组件想要修改父组件的值,使用子传父。$emit
-->
username:{{ username }}
<hr />
<input type="text" v-model="username" />
<hr />
persons:{{ persons.username }}
<hr />
<input type="text" v-model="persons.username" />
<v-child :username="username" :persons="persons"></v-child>
</div>
</template>
<script>
import vChild from "./vChild.vue";
export default {
components: {
vChild,
},
data() {
return {
username: "zs",
persons: {
username: "ls",
age: 20,
},
};
},
};
</script>
<style>
</style>
子
<template>
<div class="box">
<h4>child</h4>
username:{{username}}
<hr>
<input type="text" v-model="username">
<hr>
persons:{{ persons.username }}
<hr>
<input type="text" v-model="persons.username">
</div>
</template>
<script>
export default {
props:[ 'username','persons' ]
}
</script>
3.非父子之间组件的通信
eventBus:事件总线 (了解), 子传父的原理其实就是事件总线 。
实现非父子组件通信有三种:
1.eventBus 前提: A B需要同时存在
2.本地存储 localStorage sessionStorage
3.vuex(状态管理模式): 重点
4.cookie/session
index.vue
<template>
<div class="box">
<h4>非父子之间的通信</h4>
<!--
事件总线:eventBus
事件的订阅与发布:事件的兼听和触发
谁要数据谁就绑定事件兼听的函数,谁给数据谁就触发事件
A要B里的数据。A绑定一个事件兼听,B触发A的事件
步骤:
1. 在main.js中添加如下代码
Vue.prototype.$eventBus = new Vue()
就相当于一个公共的池子
2. 在任意文件中的this实例上都可以到 this.$eventBus 就可以访问到
因为每个.vue组件实例对象都继承于Vue构造函数
但是每个this是当前组件的实例对象,而且每个页面之间是不共享的
3. A要B里的数据。A绑定一个事件兼听,B触发A的事件
3.1 A绑定一个事件兼听
this.$eventBus.$on(事件,事件函数)
3.2 B触发A中兼听的事件函数,并且可以传参
-->
<v-a></v-a>
<v-b></v-b>
</div>
</template>
<script>
import vA from './vA.vue'
import vB from './vB.vue'
export default {
components:{
vB,
vA
},
mounted(){
// console.log( this,'index.vue' );
// console.log( this.$aa,'---aa--' );
console.log( this.$eventBus,'index.vue' );
}
}
</script>
<style>
</style>
vA.vue
<template>
<div class="box">
<h4>a</h4>
{{ username }}
</div>
</template>
<script>
export default {
data() {
return {
username: "鲁肃",
};
},
mounted() {
//console.log( this.$eventBus,'a.vue' );
this.$eventBus.$on("aEvent", (e) => {
console.log("触发了aEvent事件", e);
this.username = e.username
});
},
};
</script>
<style>
</style>
vB.vue
<template>
<div class="box">
<h4>b</h4>
<button @click="bFN">触发A中的事件</button>
</div>
</template>
<script>
export default {
methods:{
bFN(){
this.$eventBus.$emit('aEvent',{ username:'鲁班' })
}
}
}
</script>
<style>
</style>