Vue组件间的数据共享(父子,兄弟,后代,全局事件总线,Vuex)
Vue组件间的数据共享(父子,兄弟,后代,Vuex)
目录
1.父组件向子组件共享数据(父组件向子组件共享数据需要使用自定义属性)
2 子组件向父组件共享数据(子组件向父组件共享数据使用自定义事件。)
2.3 在数据接收方自定义事件(bus.on('事件名称', 事件处理函数)
后代关系组件之间的数据共享(provide 和 inject )
1.provide 和 inject数据共享(默认情况下provide和inject不是响应式的数据共享)
Vue组件间的数据共享
父子组件之间的数据共享
- 父 -> 子共享数据(vue2,3)
- 子 -> 父共享数据(vue2,3)
- 父子数据同步(vue3)
1.父组件向子组件共享数据(父组件向子组件共享数据需要使用自定义属性)
父组件:
<template>
<div class="app-container">
<h1>App 根组件</h1>
<p>{{userinfo}}</p>
<hr />
<div class="box">
<!-- 渲染 Left 组件 -->
<!-- user对象的引用,浅拷贝,
基本数据类型传值,引用数据类型传递地址 -->
<Left :msg="message" :user="userinfo">Left组件</Left>
</div>
</div>
</template>
<script>
import Left from '@/components/Left.vue'
export default {
data() {
return {
message:'hello!',
userinfo:{name:'迪丽热巴',age:18},
}
},
components:{
Left,
},
methods: {
}
},
}
</script>
子组件:
<template>
<div class="left-container">
<h3>Left 组件</h3>
<p>msg的值是:{{msg}}</p>
<p>user的值是:{{user}}</p>
//可以直接修改父组件的数据,如果是引用数据类型则改变其属性
<button @click="msg='abc'">修改msg</button>
<button @click="user.name='zs'">修改user</button>
<hr>
</div>
</template>
<script>
export default {
props:['msg','user'],
data() {
return {
}
},
methods: {
},
}
</script>
2 子组件向父组件共享数据(子组件向父组件共享数据使用自定义事件。)
子组件:
<template>
<div class="right-container">
<h3>Right 组件-----{{count}}</h3>
<button @click="add">+1</button>
<hr>
</div>
</template>
<script>
export default {
data() {
return {
/* 子组件自己的数据,将来希望把count值传给父组件 */
count:0,
}
},
methods: {
add(){
/* 让子组件的count值自增+1 */
this.count+=1
/* 修改数据时,将调用$emit(),
把自增结果传给父组件 */
this.$emit('numchange',this.count)
}
},
}
</script>
父组件:
<template>
<div class="app-container">
<h1>App 根组件---{{countFromSon}}</h1>
<p>{{userinfo}}</p>
<hr />
<div class="box">
<!-- 渲染 Right 组件 -->
<Right @numchange="getNewCount"></Right>
</div>
</div>
</template>
<script>
import Right from '@/components/Right.vue'
export default {
data() {
return {
message:'hello!',
userinfo:{name:'迪丽热巴',age:18},
/* 定义来接收子组件传过来的值 */
countFromSon:0
}
},
components:{
Right,
},
methods: {
/* 获取子组件传过来的数据 */
getNewCount(val){
console.log('numchange事件被触发',val);
this.countFromSon=val
}
},
}
</script>
3.父子组件之间数据的双向同步(Vue3.x)
父组件在使用子组件期间,可以使用 v-model 指令维护组件内外数据的双向同步
在父组件中
v-model:子组件的props属性=“data的数据”
<template>
<div>
<h1>父组件----{{count}}</h1>
<button @click="count+=1">+1</button>
<hr>
<MySon v-model:num="count"></MySon>
</div>
</template>
<script>
import MySon from './Son.vue'
export default {
name:'MyFather',
/* 父子组件之间数据的双向同步 */
data() {
return {
count:0
}
},
components:{
MySon
},
}
</script>
在子组件中
props:[ 'num' ],
emits: [ 'update:num' ]
方法中:this.$emit ( 'update:num' ,this,num+1 )
<template>
<div>
<h1>子组件 ---{{ num }}</h1>
<button @click="add">+1</button>
</div>
</template>
<script>
export default {
name:'MySon',
props:['num'],
emits:['update:num'],
methods:{
add(){
this.$emit('update:num',this.num+1)
}
}
}
</script>
>
兄弟组件之间的数据共享(EventBus)
1.vue2.x中的EventBus
- 创建 eventBus.js 模块,并向外共享一个 Vue 的实例对象
- 数据发送方:bus.$emit('事件名称', 要发送的数据)
- 数据接收方: bus.$on('事件名称', 事件处理函数(箭头函数))
兄弟组件A(数据发送方)
eventBus.js
兄弟组件C(数据接收方)
EventBus 的使用步骤
- ① 创建 eventBus.js 模块,并向外共享一个 Vue 的实例对象
- ② 在数据发送方,调用 bus.$emit('事件名称', 要发送的数据) 方法触发自定义事件
- ③ 在数据接收方,调用 bus.$on('事件名称', 事件处理函数) 方法注册一个自定义事件
2.vue3.x中的EventBus(少了$符号)
在Vue3.x中,如果是基于vite创建的vue3项目,需借助于第三方的包 mitt 来创建 eventBus 对象
2.1安装 mitt 依赖包
npm i mitt
2.2创建eventBus.js
/* eventBus.js */
/* 导入mitt包 */
import mitt from 'mitt'
/* 创建EventBus的实例对象 */
const bus=mitt()
/* 将EventBus的实例对象共享出去 */
export default bus
2.3 在数据接收方自定义事件(bus.on('事件名称', 事件处理函数)
<template>
<div>
<h1>数据接收方----{{ num }}</h1>
</div>
</template>
<script>
/* 导入eventBus.js模块,得到共享的bus对象 */
import bus from './eventBus.js'
export default {
name:'MyLeft',
data() {
return {
num:0
}
},
/* 在生命周期函数create函数
调用bus.on()方法注册一个自定义事件,
通过事件处理函数的形参接收数据 */
created(){
bus.on('countChange',(count)=>{
this.num=count
})
}
}
</script>
2.4在数据接发送方触发事件
<template>
<div>
<h1>数据发送方---count的值为:{{count}}</h1>
<button @click="add">+1</button>
</div>
</template>
<script>
/* 导入eventBus.js模块,得到共享的bus对象 */
import bus from './eventBus.js'
export default {
name:'MyRight',
data(){
return{
count:0
}
},
methods: {
add(){
this.count++
/* 调用 bus.emit
('事件名称', 要发送的数据)
方法触发自定义事件 */
bus.emit('countChange',this.count)
}
},
}
</script>
后代关系组件之间的数据共享(provide 和 inject )
只能用在爷子孙或者爷跟后代,不能用在两个无嵌套关系的孙子之间
1.provide 和 inject数据共享(默认情况下provide和inject不是响应式的数据共享)
1.1父节点通过 provide 共享数据
<template>
<div>
<h1>父组件----的color值:{{color}}</h1>
<hr>
<Two></Two>
</div>
</template>
<script>
import Two from './Two.vue'
export default {
name:'MyApp',
data() {
return {
/* 定义父组件要向子孙组件共享的数据 */
color:'red',
}
},
provide(){
//返回要共享的数据对象
return{
color:this.color
}
},
components:{
Two
}
}
</script>
1.2子孙节点通过 inject 接收数据
<template>
<div>
<h1>孙组件---{{color}}</h1>
</div>
</template>
<script>
export default {
name:'MyThree',
/* 子孙节点可以使用 inject 数组,
接收父级节点向下共享的数据 */
inject:['color']
}
</script>
2.provide 和 inject数据共享(响应式)
2.1父节点对外共享响应式的数据
<template>
<div>
<h1>父组件----的color值:{{color}}</h1>
<button @click="color='blue'">变bule</button>
<hr>
<Two></Two>
</div>
</template>
<script>
import Two from './Two.vue'
/* 按需导入computed函数 */
import {computed} from 'vue'
export default {
name:'MyApp',
data() {
return {
color:'red',
}
},
provide(){
//返回要共享的数据对象
return{
/* 使用computed函数,
将共享的数据包裹成响应式数据 */
color:computed(()=>this.color)
}
},
components:{
Two
}
}
</script>
2.2子孙节点使用响应式的数据
<template>
<div>
<!-- 响应式的数据,必须以.value的形式进行使用 -->
<h1>孙组件---{{color.value}}</h1>
</div>
</template>
<script>
export default {
name:'MyThree',
inject:['color']
}
</script>
全局事件总线
一种组件间通信的方式 适用于任意组件间通信
- 1.指定事件总线对象
-
new Vue({ beforeCreate () { // 尽量早的执行挂载全局事件总线对象的操作 Vue.prototype.$globalEventBus = this }, }).$mount('#root')
- 2.绑定事件
-
this.$globalEventBus.$on('deleteTodo', this.deleteTodo)
- 3.分发事件
-
this.$globalEventBus.$emit('deleteTodo', this.index)
- 4.解绑事件
-
this.$globalEventBus.$off('deleteTodo')
1.安装全局事件总线:在入口文件main.js中
// 该项目的入口文件
import Vue from 'vue'
// 引入App组件 他是说要组件的父组件
import App from './App.vue'
new Vue({
el:'#app',
render: h => h(App),
//利用钩子函数挂载属性
beforeCreate(){
Vue.prototype.$bus = this
//安装 全局事件总线 this指向vue原型
//$bus就是当前应用的vm
}
})
2.使用事件总线:在需要接收的组件School中
接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。 最好在beforeDestroy钩子中 用$off去解绑当前组件所用到的事件
<template>
<div class="school">
<h2>名称:{{ name }}</h2>
<h2>学校地址:{{ address }}</h2>
</div>
</template>
<script>
export default {
name: "School",
props:['getSchoolName'],
data() {
return {
name: "迪丽热巴",
address: "新疆",
};
},
mounted(){
//绑定对应的自定义事件
this.$bus.$on('hello',(data)=>{
console.log('我是School组件.我收到了数据',data);
//接收的一方完成之后,最好解绑某一个事件
})
},
//解绑某事件
beforeDestroy(){
this.$bus.$off('hello')
//有事件名代表解绑对应的事件
//无事件名则全部解绑(如有人用 则不起作用)
}
};
</script>
3.在要传的组件Student中
提供数据:this.$bus.$emit('xxxx',数据)
<template>
<div class="student">
<h2>学生姓名:{{ name }}</h2>
<h2>学生性别:{{ sex }}</h2>
<button @click="sendStudentName">把Student组件的name传给School组件</button>
</div>
</template>
<script>
export default {
name: "Student",
data() {
return {
name:"迪丽热巴啊",
sex:24,
};
},
methods:{
sendStudentName(){
//触发对应的自定义事件
this.$bus.$emit('hello',this.name)
//绑定的事件名 不可重复
}
}
};
</script>
消息订阅与发布(第三方库pubsub)
一种组件间通信的方式,适用于任意组件间通信。
- 接收和发送数据方都要引入第三方库
- 因为消息订阅与发布时调用第三方库,所以试调的时候是看不到报错和提示的。
使用步骤:
- 安装pubsub:
npm i pubsub-js
- 引入:
import pubsub from 'pubsub-js'
- 接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。
//定义一个School组件用于接收Student组件传递过来的数据
<template>
<div class="scl">
<h2>名称:{{ schoolName }}</h2>
<h3>地址:{{ addr }}</h3>
</div>
</template>
<script>
// 给接收数据方引入组件
import pubsub from "pubsub-js";
export default {
name: "School",
data() {
return {
userame: "迪丽热巴",
addr: "新疆",
};
},
//方法一---------------
mounted() {
//设置const puId 是为了方便取消订阅的时候使用,放在this身上才可以被beforeDestroy里的方法读取到
this.pubId = pubsub.subscribe("hello", function (msgName, data) {
//消息以参数的形式被接受,当不配置参数的时候则传递的数据不能接收但是可以调用这个回调函数
//该方法的第一个参数代表发布消息的名字,第二个及后面的才是传递的数据
console.log("有人发布了hello消息,hello消息的回调执行了", msgName, data);
//测试this是什么
console.log(this); //输出为undefined因为这里的this是第三方库的this(用的普通函数)
//如果要this为vue实例则最好用箭头函数,或者写成method方法形式的接收方法
//方法二------methods方法-------------------
//methods:{
//demo(msgName,data){
//console.log("有人发布了hello消息,hello消息的回调执行了", msgName, data)
// }
//}
//mounted(){
//this.pubId = pubsub.subscribe('hello',this.demo)
//},
//-------------------------------------------
beforeDestroy() {
//消息订阅的方法有点像定时器,如果要取消订阅要通过id取消,所以可以给上面订阅方法一个id,方便取消绑定使用
pubsub.unsubscribe(this.pubId); //取消订阅
},
};
</script>
- 提供数据:
pubsub.publish('xxx',数据)
- 最好在beforeDestroy钩子中,用
PubSub.unsubscribe(pid)
去取消订阅。
//定义一个Student组件用于提供数据
<template>
<div class="stu">
<h2>学生姓名:{{ studentName }}</h2>
<h3>学生年龄:{{ age }}</h3>
<button @click="sendStudentName">studen学生姓名给School</button>
</div>
</template>
<script>
// 给发送数据方也要引入相关组件
import pubsub from "pubsub-js";
export default {
name: "Student",
data() {
return {
studentName: "小王八",
age: 19,
};
},
methods: {
sendStudentName() {
pubsub.publish("hello", 666);
},
},
};
</script>
Vuex(终极的组件之间的数据共享方案)
更多推荐
所有评论(0)