前端vue入门(纯代码)11

news2024/12/24 9:50:22

11.全局事件总线(Global Event Bus)

全局事件总线:实现任意组件间通信

【原理图】

在这里插入图片描述

  • 结合上图,假若C组件想要传递数据给A组件,那么,就通过全局事件总线在A组件中绑定【$on】一个自定义事件demo,并界定一个参数来接收传递的数据,同样在C组件中,就需要通过全局事件总线对自定义事件demo进行触发【$emit】,并传递参数,这样就实现了任意组件之间的通信。

  • 简单理解,全局事件总线其实就是一个中间介质,组件间的相互通信借助于这个中间介质,通过这个中间转换介质,从而完成数据的传递与接收,实现组件间的相互通信。

  • 全局事件总线是一个独立存在的部分,要想实现组件间的相互通信,又是自定义事件,那就要满足两个条件:

    【1】. 所有的组件都能访问到全局事件总线【X总线】

    【2】. 可以调用$on【绑定】,$off【解绑】,$emit【触发事件】


全局事件总线应该安装在哪里呢?

  • 安装全局事件总线前需要考虑:如果要所有组件对象【vm,vc】都能够获取到事件总线
  • 从下图可以看出,当组件实例化对象vc获取数据时,会首先找到组件原型对象,如果该组件实例对象中没有此数据,那么就找到Vue的原型对象,Vue的原型对象只有一个,所有组件都能够获取到它的数据,所以事件总线要安装到Vue的原型对象上

在这里插入图片描述

结合组件的内置关系:

VueComponent.prototype.__proto__ === Vue.prototype【Vue的原型对象】

这个关系在作用就在于可以让 组件实例对象(vc,vm) 可以访问到Vue原型对象【Vue.prototype】上的属性和方法

  • 回顾知识:关于VueComponent:

    1.A、B、C子组件本质上是一个名为VueComponent的构造函数,且不是程序员定义的,是调用Vue.extend()生成的

    2.只需要写<A/>或<A></A>,Vue解析时会帮我创建A组件的实例对象,

    3.每次调用Vue.extend,返回的都是一个全新的VueComponent

  • 1. 由于是在入口文件main.js中引入的Vue,所以事件总线需要配置到main.js当中

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false

//创建vm
new Vue({
	el:'#app',
	render: h => h(App),
  // 生命周期钩子beforeCreate中模板未解析,且this是vm
  beforeCreate() {
		Vue.prototype.$bus = this  //安装全局事件总线$bus
	}
})
  • 为什要在Vue实例对象中采用生命周期钩子beforeCreate安装事件总线?
    • 由生命周期beforeCreate此时只是完成了初始化工作,创建了Vue实例对象,但是模板并没有解析,数据代理并没有运转。
  • 2. 接下来,我们就要对想要接收到数据的组件进行自定义事件的绑定,简单来说就是,谁【比如:A】要接收数据,自定义事件就绑定在谁【比如:A】身上 【$on()里面要是用箭头函数】
  • 绑定全局事件总线
mounted(){
  // 绑定自定义事件
  this.$bus.$on('自定义事件名', (接收参数)=>{
    console.log('我是TestB组件,收到了数据', 接收参数);
  })
}
  • 3. 最后一步,全局事件总线的触发,事件的触发是在发送数据的组件中完成的,简单来说,谁【比如:B】是数据的发送者,谁【比如:B】就来触发事件
  • 触发全局事件总线
 methods:{
  // 触发事件,事件名不能重复
  触发事件方法名(){
    this.$bus.$emit('自定义事件名', 传递参数);
  }
},
  • 4. 在得到数据之后,解绑事件,提高性能,在beforedestroy生命周期钩子中,用**$off**解绑当前组件所用到的数据
  • 解绑自定义事件
// 销毁对应自定义事件
beforeDestroy(){
  this.$bus.$off('自定义事件名')
}

完整代码:

School.vue组件

<template>
	<div class="school">
		<h1>School组件</h1>
		<!-- 给子组件的实例对象VC绑定了事件getName,该事件触发会调用函数getStudentName -->
		<h2>兄弟组件Student传过来的name:{{ StudentName }}</h2>
		<h2>兄弟组件Student传过来的age:{{ StudentAge }}</h2>
	</div>
</template>

<script>
export default {
	name: 'School',
	data() {
		return {
			StudentName: '',
			StudentAge: '',
		};
	},
	mounted() {
		// 绑定自定义事件haha
		this.$bus.$on('haha', (...params) => {
			console.log('School组件里的', this);
			this.StudentName = params[0];
			this.StudentAge = params[1];
			console.log('我是School组件,收到了数据', params);
		});
	},
  // 销毁对应自定义事件
	beforeDestroy() {
    // 解绑自定义事件
    this.$bus.$off('haha')
  },
};
</script>

<style scoped>
.school {
	background-color: rgb(73, 192, 150);
}
</style>

  • ...params:可以以数组的形式接收多个参数。

Student.vue组件

<template>
	<div class="student">
    <h1>Student组件信息</h1>
		<h2>学生姓名:{{ name }}</h2>
		<h2>学生性别:{{ sex }}</h2>
		<h2>学生年龄:{{ age }}</h2>
		<h2>学生成绩:{{ score }}</h2>
		<button class="haha" @click="sendStudentlName">
      <h2>点击此处给兄弟组件School传值</h2></button>
	</div>
</template>

<script>
export default {
	name: 'Student',
	data() {
		return {
			name: '何大春',
			sex: '男',
			age: '22',
			score: '88',
		};
	},
	methods: {
    sendStudentlName(){
      console.log("Student组件里的",this.name);
      // 传给School组件两个参数
      this.$bus.$emit('haha',this.name,this.age)
    }
	},
};
</script>

<style lang="less" scoped>
.student {
	background-color: tomato;
	padding: 50px;
	margin-top: 50px;
	margin-left: 50px;
	width: 300px;
	height: 350px;
}
.h2 {
  padding: 5px;
  margin: 5px 5px 5px 5px;
}
.haha {
  background-color: rgb(211, 233, 130);
}
</style>

结果展示:

在这里插入图片描述

补充知识点:

问题1:“全局事件总线”需要哪些特点?

  • 1)被所有组件(vc、vm)能够看得见
  • 2)能够调用$on、$emit、$off

问题2:“Vue原型对象上面的所有属性和方法是给谁用的?

  • 是给所有的vm和vc使用的

问题3:为什么定义“全局事件总线”要放在main.js文件中?

  • 因为哪里引入Vue,哪里才会去定义“全局事件总线”

问题4:“为什么定义“全局事件总线”要放在beforeCreate的钩子函数中?

  • 1)beforeCreate钩子函数里this指代new出来的vm

  • 2)在beforeCreate钩子函数里模板还没解析,数据监测和数据代理也还没完成呢。也就是说借助这个beforeCreate钩子函数你把想做的事儿做好了,原型上该放的放好了,随后模板开始解析,等组件执行的时候你该放的都放好了,后续才做都不会产生影响。

问题5:如何避免在使用“全局事件总线”时自定义函数名重名使用问题?比如组件1使用自定义函数名叫demo,那组件2不全文搜索也使用了自定义函数名也叫demo,这就混了

  • 真实项目中src目录下创建一个config文件夹,里面创建个constants常量文件,里面用来定义要使用的自定义函数名,方便别人查看并避免重名问题。

问题6:“为什么要在组件销毁之前,把“全局事件总线”中定义的自定义事件函数解绑?那“知识点组件自定义事件”中咋没说解绑的事儿呢?

  • “组件自定义事件”中,组件销毁了== vc销毁了,vc销毁了自定义事件也就销毁了,而“全局事件总线”中定义的自定义事件是一直存在的,哪怕使用组件销毁了,但是Vue实例定义的“全局事件总线”中还是会存在自定义事件,所以需要在组件销毁之前进行解绑。

注意7:销毁“全局事件总线”中定义的自定义事件请放在beforeDestroy()钩子中

注意8:子组件中使用“全局事件总线”时this.$bus.$on()中回调配置要使用箭头函数,不要使用普通函数,普通函数中this指代vue实例,而箭头函数中this才指代vc,因为最终要在school组件上接收平行组件发过来的消息,所以要使用vc,而不是要使用vue实例,因为vue实例不是我们最终要的。

mounted(){
  // 绑定自定义事件
  this.$bus.$on('自定义事件名', (接收参数)=>{
    console.log('我是TestB组件,收到了数据', 接收参数);
  })
},
	mounted() {
		// 绑定自定义事件haha
		this.$bus.$on('haha', (...params) => {
			console.log('School组件里的', this); //this = vc
			this.StudentName = params[0];
			this.StudentAge = params[1];
			console.log('我是School组件,收到了数据', params);
		});
	},

总结:

全局事件总线实现了任意组件间的通信,有效简化了开发过程中一些数据传递的操作,同时也提高了程序的性能,但是值得注意的是,全局事件总线之所以叫全局,是因为任何组件都可以访问,这就导致如果大量组件都绑定了全局事件总线,难免会造成代码混乱,且自定义事件名可能发生重复的问题,所以在开发中,使用全局事件总线时要根据实际业务情况进行选择。

  1. 全局事件总线:一种组件间通信的方式,适用于任意组件间通信。

  2. 安装全局事件总线:

    new Vue({
    	......
    	beforeCreate() {
    		Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
    	},
        ......
    }) 
    
  3. 使用事件总线:

    1. 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。

      methods(){
        demo(data){......}
      }
      ......
      mounted() {
        this.$bus.$on('xxxx',this.demo)
      }
      
    2. 提供数据:this.$bus.$emit('xxxx',数据)

  4. 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。

olor:red">回调留在A组件自身。

  ```js
  methods(){
    demo(data){......}
  }
  ......
  mounted() {
    this.$bus.$on('xxxx',this.demo)
  }
  ```
  1. 提供数据:this.$bus.$emit('xxxx',数据)

  2. 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/671644.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如果我们20年后仍然在讨论Kubernetes,那将是技术上悲哀的时刻

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 Kelsey Hightower Google Cloud首席开发者 引子 在 Kubecon 上&#xff0c;Kelsey Hightower 曾经遇到过一个带有 Kubernetes 纹身的人&#xff0c;这让他开始…

工业相机的镜头如何选择?

相机的镜头如何计算&#xff0c;如果看公式的话&#xff0c;需要知道相机sensor的尺寸&#xff0c;相元的尺寸&#xff0c;计算起来数据也比较复杂&#xff0c;下面教大家一个简单的方法&#xff0c;就是如何借助镜头计算工具来使用。 巴斯勒相机的镜头选型地址 工业镜头选型…

我们该如何提升测试效率?

在大部分研发项目经理心中&#xff0c;进度往往会放在第一位&#xff0c;其次是成本&#xff0c;最后是质量&#xff0c;当然人员队伍最好也要稳定。天下武功&#xff0c;唯快不破&#xff1a;进度 > 成本 > 质量 > 人。 这个说法并不是绝对&#xff0c;今天我们并不是…

【Linux】线程同步条件变量

文章目录 一. 为什么要线程同步二. 条件变量1. 条件变量的使用2. 简单使用 结束语 一. 为什么要线程同步 通过互斥量&#xff0c;也就是加锁解锁&#xff0c;我们可以实现线程互斥&#xff0c;但是当访问的临界区代码较少时&#xff0c;线程执行会出现不停加锁解锁的情况。这样…

uniapp项目中使用vue3开发多端项目实践

目录 1、使用版本说明2、创建项目3、运行项目4、uniapppinia本地缓存插件PiniaPluginUnistorage5、 uni-app vue3 vite ts 项目结构 本项目中使用vue3开发多端项目实践&#xff0c;hbuilderx内置vue3模块&#xff0c;使用了vite4.x构建&#xff0c;编译构建项目的速度比火箭…

dpmsolver 论文核心整理

推导 DPM-Solver1的误差 由正文所述&#xff1a; 利用泰勒展开&#xff1a; B.3式就是换了个元 δ λ − λ s λ t − λ s \delta\frac{\lambda-\lambda_s}{\lambda_t-\lambda_s} δλt​−λs​λ−λs​​&#xff0c;代入论文公式(3.4)的积分项&#xff08;不含系数&…

一套完整的工厂车间现场管理指南,车间主管收藏好了!

车间是企业的基本层&#xff0c;搞好车间现场管理&#xff0c;有利于企业增强竞争力&#xff0c;提高产品质量和员工素质&#xff0c;保证安全生产&#xff0c;而车间班组长是生产线的主要管理者&#xff0c;是直接“当家人”&#xff0c;对生产现场状况了如指掌&#xff0c;对…

0001Java程序设计-SSM校园快递系统的设计与实现

摘 要 21世纪之后&#xff0c;全球信息化逐渐加快&#xff0c;尤其表现在近几年来电商行业的飞速发展&#xff0c;人们足不出户就可以买到自己想要的商品&#xff0c;尤其是青年大学生&#xff0c;追求新颖&#xff0c;更加乐忠于网络购物。网络购物的增加&#xff0c;就导致物…

【二】python爬虫进行AES解密遇到的问题

1、TypeError: Object type <class ‘str’> cannot be passed to C code 报错如下&#xff1a; File "C:\Python311\Lib\site-packages\Crypto\Util\_raw_api.py", line 143, in c_uint8_ptrraise TypeError("Object type %s cannot be passed to C cod…

【使用Spring Cloud Gateway构建微服务网关】—— 每天一点小知识

&#x1f4a7; 使用 S p r i n g C l o u d G a t e w a y 构建微服务网关 \color{#FF1493}{使用Spring Cloud Gateway构建微服务网关} 使用SpringCloudGateway构建微服务网关&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主…

54 KVM工具使用指南-vmtop使用指南

文章目录 54 KVM工具使用指南-vmtop使用指南54.1 概述54.1.1 多架构支持54.1.2 显示项说明54.1.2.1 AArch64和x86_64架构公共显示项54.1.2.2 仅AArch64架构的显示项54.1.2.3 仅x86_64架构的显示项 54.2 使用方法54.2.1 语法格式54.2.2 选项说明54.2.3 快捷键 54.3 示例 54 KVM工…

MSP432学习笔记10:串口接收字符串命令并执行任务

今日终于得以继续我的MSP432电赛速通之路&#xff1a; 串口通信是单片机需要学习深入的一个很重要的板块&#xff0c;通过串口&#xff0c;我们可以实现许多数据收发与调试工作&#xff0c;可谓是非常方便快捷。 今日就跟随我的脚步&#xff0c;逐步扎实地学习如何编程MSP432…

2023-06-21:redis中什么是BigKey?该如何解决?

2023-06-21&#xff1a;redis中什么是BigKey&#xff1f;该如何解决&#xff1f; 答案2023-06-21&#xff1a; 什么是bigkey bigkey是指存储在Key-Value数据库中的键对应的值所占用的内存空间较大。举个例子&#xff0c;如果值是字符串类型&#xff0c;它可以达到最大512MB的…

堆体系结构概述

1、逻辑概述 2、堆会出现的异常 3、物理上划分 &#xff08;1&#xff09;新生区 新生区是类的诞生、成长、消亡的区域&#xff0c;一个类在这里产生&#xff0c;应用&#xff0c;最后被垃圾回收器收集&#xff0c;结束生命。新生区又分为两部分&#xff1a; 伊甸区&#xff0…

Goby 漏洞发布|WordPress User Post Gallery 插件 upg_datatable 远程代码执行漏洞(CVE-2022-4060)

漏洞名称&#xff1a;WordPress User Post Gallery 插件 upg_datatable 远程代码执行漏洞&#xff08;CVE-2022-4060&#xff09; English Name&#xff1a;WordPress plugins User Post Gallery upg_datatable RCE Vulnerability (CVE-2022-4060) CVSS core: 9.8 影响资产数…

Observability:如何把 Elastic Agent 采集的数据输入到 Logstash 并最终写入到 Elasticsearch

在之前的文章 “安装独立的 Elastic Agents 并采集数据 - Elastic Stack 8.0”&#xff0c;我们详述了如何使用 No Fleet Server 来把数据写入到 Elasticsearch 中。在今天的文章中&#xff0c;我们来详述如下使用 Elastic Agents 在独立&#xff08;standalone&#xff09;模式…

Gradio Blocks:自定义交互式Web应用和演示

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

GitPySearch: 全局Python代码搜索工具

一 、背景 在某些情况下&#xff0c;我们需要快速了解哪些项目包含特定的配置&#xff0c;例如使用了fastjson库或数据库的连接配置。然而&#xff0c;在GitLab上逐个代码仓库进行搜索是非常耗时的。为了提高效率&#xff0c;我们开发了一个Python脚本工具&#xff0c;用于实现…

PostgreSQL的优势:为何它成为主流数据库管理系统

PostgreSQL的优势&#xff1a;为何它成为主流数据库管理系统 Stack Overflow 2023年报告PostgreSQL和MySQL同异我们在开发中如何选择PostgreSQL和MySQL呢&#xff1f; 摘要&#xff1a;本文主要比较了PostgreSQL和MySQL这两个流行的关系型数据库管理系统。我们首先介绍了它们的…

屏蔽箱的材质结构和使用事项介绍

屏蔽箱是一种用于屏蔽机电波干扰的设备&#xff0c;通常用于电磁兼容测试、天线测试、短波收发等需要屏蔽电磁辐射噪声的场合。这种箱子通常由导电或者导磁材料制成&#xff0c;内部配备高效屏蔽材料&#xff0c;能够在一定范围内有效地屏蔽电磁波辐射&#xff0c;避免电磁波干…