vue事件车的原理与标准写法实现兄弟组件的传值

news2024/11/14 14:42:46

目录

  • 前言
  • 一,全局事件总线介绍
    • 1.1 原理介绍
    • 1.2 x需要满足的条件
  • 二,知识点的复习
    • 2.1 vc是什么
    • 2.2 vm管理vc如何体现
    • 2.3 原型
    • 2.4 上述知识的串联
  • 三,实现需求
    • 3.1 x的编写及讲解
    • 3.2 使用x
  • 四,标准写法
    • 4.1 写法改动
    • 4.2 销毁
  • 五 关键代码
  • 后记

前言

在没有学习兄弟组件的传值时,兄弟组件之间传值可以借助它们共同的父组件:把值传给它们的父组件,再按需要取值(子传父,父再传子)。这样做十分麻烦,本节将提供更简单的做法——事件总线。

注意,本节内容最好是在熟悉了父子组件的相互通讯的前提下再进行学习,如果不太熟悉可以参考下面两篇博客(第二篇文章原理讲解更多):Vue组件之间的数据共享详解

一,全局事件总线介绍

1.1 原理介绍

如图,组件结构图如下。现在我们有一个需求,想要将D组件中的数据以参数的形式传递给A组件。
在这里插入图片描述

怎么实现呢?利用以前的想法,我么可以让D组件先把数据传递给App组件,然后A组件再从App组件中获取数据。这个过程可以利用给组件设置自定义事件来实现。在这个过程中,App组件成了一个联络人。但是这样的方法,其实是绕了很大一个湾子去实现目的。

本节,我们将介绍一个很简单的方法:设置一个x,要求x也可以充当向上面app一样的联络人。如下图所示:同样是将信息从D传到A。我们可以在过程1中,在A中给x绑定一个自定义事件demo,在2过程中,x身上的demo事件被触发,x事件的回调在A中执行,参数成功传给了A。
在这里插入图片描述

1.2 x需要满足的条件

通过上述的讲解,可以看出x十分重要,那么,现在我们为来探讨x究竟是什么。

x的要求:x需要能够被所有组件看见(所有组件都能访问到x),x还需要能够使用on和emit。

我们可以推理一下,满足第二个条件,x可以是一个vc,也可以是vm。满足第一个条件的,也可以是一个vc或者是vm。

上面说了很多vc和vm,为了方便大家学习,在第二节会说清vc和vm的关系,以及对一些相关知识的复习。如果知识很熟可以跳过。

二,知识点的复习

2.1 vc是什么

vc的全称VueConpoment。vc的本质是一个构造函数。

而我们每写一个组件,组件的本质就是vc,也就是构造函数。

每用一个组件在App中,那么就相当于该组件多了一个组件的实例对象。

一个组件在做项目时会被复用多次,这些被复用的就是组件的实例对象:
在这里插入图片描述
在这里插入图片描述

2.2 vm管理vc如何体现

体现vm为何能管理vc,只需要看vm中是否有vc:
在这里插入图片描述

2.3 原型

这里要从构造函数聊起,在es6之前,没有类和对象,但是通过构造函数与构造函数的实例对象同样也可以实现面向对象编程。

在构造函数的相关知识中,构造函数的每一个实例对象都可以使用构造函数中的方法,但是有一个弊端:占用内存。如下图:
在这里插入图片描述
在这里插入图片描述
如何解决弊端:原型。构造函数中的原型:prototype,如果我们不把方法放在构造函数中,而是放在构造函数的原型对象上,依旧可以实现共享,并且不会占用内存。
在这里插入图片描述
在这里插入图片描述
原型中的方法是所有构造函数的实例对象共享的。也就是说,所有的实例对象都可以访问原型中的方法。

以上就是对原型知识的普及,如果觉得不够,可以查看博客:构造函数与原型对象,这里有对相关知识的详细讲解。

2.4 上述知识的串联

以上是我在学习这一块时复习的知识,以及引发的一些思考。为什么要讲解上述知识,我们回到对x的要求上。x需要能够被所有的组件看见,我们可以考虑把x放在prototype上;x需要能够使用on和emit,而组件可以,vm管理vc,所以vm也可以。因此,x可以是一个新的vm也可以是一个新的vc。这块知识可能有些晦涩,下面会结合实例理解。

三,实现需求

3.1 x的编写及讲解

如图所示,在main.js中定义一个vc并把它放到原型上去:
在这里插入图片描述
这里我来解释一下Demo是什么。Vue.extend()用来创建一个组件。组件本质是一个构造函数,由Vue.extend()自动生成。
如果向了解extend用法可以参考此博客:用原生的方式写vue组件之深度剖析组件内部的原理。
Demo是一个组件(构造函数),那么demo就是Demo的实例对象。Vue.prototype.x=demo, 是在Vue原型上创建了一个x。然后x是一个组件的实例对象。由于Vue的原型可以被所有组件实例对象访问,所以x可以被所有组件实例对象访问;而demo本质是一个组件的实例对象,所以可以使用on和emit,因此就达到了对x的两个要求。

3.2 使用x

那么,既然已经写好了x我们就可以来用到x了。如下图所示,这是要传递信息的一方,相当于刚说的A,在A中利用on给x定义一个自定义事件hello,并且后面有一个回调函数。如果对自定义方法不了解可以参考此博客:vue中利用ref实现更灵活的子向父传值中有涉及到。
在这里插入图片描述
既然已经绑定在了x上,我们可以在传值方使用emit调用此自定义方法:
在这里插入图片描述
这样一来就可以实现兄弟组件的数据传递。

四,标准写法

4.1 写法改动

标准写法的原理与上面一样。
标准写法同样是在main.js中,不同的是,x改为$bus,这个名字是为了适应vue的取名风格,其实什么名字都不重要,x也可以;还有就是,之前是创建了一个组件的实例对象,现在直接把vm拿出来,如下图所示:
在这里插入图片描述
这里需要解释几个问题:

1.使用beforeCreate:是因为,一般使用兄弟组件互传数据,最终的目的大多是为了使用数据,并呈现在页面上。而beforeCreate钩子时,数据监测数据代理都没有实现,且访问不到data的数据,所以数据要在还没有对数据进行处理的时候完整。

2.为什么用this:之前我们说可以用vm,但是如果在vm定义好后等于vm,页面已经更新完成,此时 $bus就没什么意义。如果在vm定义前等于vm,vm并未存在,无法令值为vm;所以利用钩子函数,后面赋值为this,是标准写法。

既然改动了$x,那么所有的 $x都要改为 $bus

学习了上面的原理,大家应该都对$bus有了了解,它叫事件总线,还叫事件车,组件之间的传递可以通过它来实现。

4.2 销毁

上文交代了事件车的原理,组件间数据的传递都可以用到它,但一般在使用中,一旦用完,为了加快项目运行的效率我们最好在beforeDestory钩子中解绑档期那组件所用到的事件,注意,只是销毁那个事件,而不是销毁所有。如下图所示,利用off即可。
在这里插入图片描述

五 关键代码

main.js

import Vue from 'vue'
import App from './compoments/App'

//写一个demo组件


// const Demo = Vue.extend({})//demo是组件的g构造函数
// const demo = new Demo()//组件的实例对象
// Vue.prototype.x = demo



new Vue({
    el: '#app',
    render: h => h(App),
    beforeCreate() {
        Vue.prototype.$bus = this//标准写法,安装全局事件总线
    }
})

App.vue

<template>
  <div>
    <School></School>
    <Student></Student>
  </div>
</template>

<script>
import School from './School.vue'
import Student from './Student.vue'
export default {
  components: { School, Student },
    name: 'App'
}
</script>

<style>

</style>

接受数据的一方:

<template>
  <div>
    <School></School>
    <Student></Student>
  </div>
</template>

<script>
import School from './School.vue'
import Student from './Student.vue'
export default {
  components: { School, Student },
    name: 'App'
}
</script>

<style>

</style>

传数据的一方:

<template>
  <div>
    <h2>学校名称: {{ name }}</h2>
    <h2>学校地址: {{ address }}</h2>
    <button @click="sendSchoolName">发送学校信息</button>
  </div>
</template>

<script>
import School from './School.vue'
import Student from './Student.vue'
export default {
    name: 'School',
    data() {
        return {
            name: '尚硅谷',
            address: '北京'
        }
    },
    components: {
        School, Student
    },
    methods: {
      sendSchoolName() {
        this.$bus.$emit('hello', this.name)
      }
    }
}
</script>

<style>

</style>

后记

以上是对事件车的原理讲解与写法说明,希望本节内容可以帮到读者朋友。有什么不对之处欢迎大家批评指正,同时也欢迎关注,后期会带来更认真的内容!

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

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

相关文章

有关BMP位图的分析

1、BMP是什么&#xff1f; BMP是 Bitmap&#xff08;位图&#xff09;的简称&#xff0c;是windows显示图片的基本格式。 在windows下&#xff0c;任何格式的图片文件&#xff08;包括视频播放&#xff09;都要转化为位图才能显示出来&#xff0c;各种各样格式的图片文件也都…

9.Java数组知识大全

文章目录前言一、数组介绍二、数组的定义域静态初始化三、数组元素访问数组地址中的小拓展:四、数组遍历1.获取数组里面的元素2.把数据存储到数组中3.遍历数组的最快方式4.遍历数组并求和5.统计个数6.变化数据五、数组动态初始化1.数组默认初始化值的规律2.数组动态初始化和静态…

单绞机控制算法模型(Simulink仿真)

线缆行业单绞机PLC控制算法详细解读可以参看下面的文章链接: 线缆行业单绞机控制算法(详细图解+代码)_RXXW_Dor的博客-CSDN博客在了解单绞机之前需要大家对收放卷以及排线控制有一定的了解,不清楚的可以参看下面几篇博客,这里不再赘述,受水平和能力所限,文中难免出现错…

【JavaEE】认识线程Thread类及常用方法线程状态

目录 一&#xff1a;认识线程&#xff1a; 二、线程的优点&#xff1a; 三、进程和线程的区别&#xff08;面试题&#xff09;&#xff1a; 四、第一个多线程程序&#xff1a; 五、创建线程的方式&#xff1a; 六、Thread类及常用方法 Thread类常见构造方法&#xff1…

整理介绍字符函数和字符串函数+内存函数

本篇重点介绍处理字符和字符串的库函数的使用和注意事项 本篇重点本篇重点介绍处理字符和字符串的库函数的使用和注意事项前言&#xff1a;求字符串长度strlen拷贝字符串函数strcpy&#xff08;追加&#xff09;连接字符串函数strcat比较两个字符串函数strcmp对上面改进字符串函…

Mac应用程序无法打开或文件损坏的处理方法

很多用户在安装 盗版 Mac软件的时候&#xff0c;经常会遇到提示“xxx.app已损坏&#xff0c;打不开。您应该将它移到废纸篓“或”打不开的xxx.app&#xff0c;因为它来自身份不明的开发者”&#xff0c;等多种打不开盗版软件的各种提示&#xff0c;正版软件则不会出现。 错误截…

17种编程语言实现排序算法-基数排序

开源地址 https://gitee.com/lblbc/simple-works/tree/master/sort/ 覆盖语言&#xff1a;C、C、C#、Java、Kotlin、Dart、Go、JavaScript(JS)、TypeScript(TS)、ArkTS、swift、PHP。 覆盖平台&#xff1a;安卓(Java、Kotlin)、iOS(SwiftUI)、Flutter(Dart)、Window桌面(C#)、…

事件冒泡和时间捕获

事件冒泡和事件捕获 最近&#xff0c;在复习Vue的时候&#xff0c;发现自己对于事件冒泡和事件捕获的理解存在一定的错误。于是想写一份笔记来总结一下事件冒泡和事件捕获。✌✌✌ 一、事件 1、事件的三个阶段&#xff1a;事件捕获->事件目标->事件冒泡 捕获阶段&am…

MySQL 性能优化浅析及线上案例

作者&#xff1a;京东健康 孟飞 1、 数据库性能优化的意义 业务发展初期&#xff0c;数据库中量一般都不高&#xff0c;也不太容易出一些性能问题或者出的问题也不大&#xff0c;但是当数据库的量级达到一定规模之后&#xff0c;如果缺失有效的预警、监控、处理等手段则会对用户…

设计模式学习(十二):Decorator装饰器模式

一、什么是Decorator模式假如现在有一块蛋糕&#xff0c;如果只涂上奶油&#xff0c;其他什么都不加&#xff0c;就是奶油蛋糕。如果加上草莓&#xff0c;就是草莓奶油蛋糕。如果再加上一块黑色巧克力板&#xff0c;上面用白色巧克力写上姓名&#xff0c;然后插上代表年龄的蜡烛…

JavaEE5-Spring更简单的读取和存储对象

目录 1.存储Bean对象 1.1.前置工作&#xff1a;在配置文件中设置bean扫描的根路径&#xff08;重要&#xff09; 1.2.添加注解存储Bean对象到Spring中 1.2.1.类注解(添加到某个类上&#xff0c;将当前的类存储到Spring中)&#xff1a;Controller&#xff0c;Service&#x…

树,堆,二叉树的认识

1.树概念及结构 1.1树的概念 注意&#xff1a;树形结构中&#xff0c;子树之间不能有交集&#xff0c;否则就不是树形结构 1.2 树的相关概念 1.3 树的表示 树结构相对线性表就比较复杂了&#xff0c;要存储表示起来就比较麻烦了&#xff0c;既然保存值域&#xff0c;也要保存…

Gateway服务网关

Gateway服务网关一、网关介绍二、gateway快速入门1.创建gateway服务&#xff0c;引入依赖2.编写启动类3.编写基础配置和路由规则4.重启测试5.网关路由的流程图三、断言工厂四、过滤器工厂1.路由过滤器的种类2.请求头过滤器3.默认过滤器4.总结五、全局过滤器1.全局过滤器作用2.自…

fpga实操训练(系统开发和硬件接口)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 相信很多学习fpga的同学都会有这样的一个感受,一开始fpga学习还比较简单,但是一旦涉及到呼吸灯、uart、spi、iic、ddr2后面就会越来越难。遇到这样的困难之后,学习的激情一下子少…

从零搭建一个组件库(一)项目环境搭建

文章目录前言monorepo架构1.monorepo架构的优势2.使用pnpm搭建monorepo架构&#xff08;1&#xff09;全局安装pnpm&#xff08;2&#xff09;初始化项目&#xff08;3&#xff09;新建workspace.yaml文件4.不同包之间的相互引用TypeScript支持1.安装TypeScript2.初始化TypeScr…

http三次握手四次挥手详解

1、 TCP的三次握手和四次挥手实质就是TCP通信的连接和断开。 三次握手&#xff1a;为了对每次发送的数据量进行跟踪与协商&#xff0c;确保数据段的发送和接收同步&#xff0c;根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系&#xff0c;并建立虚连接。 四次挥…

C++6:STL-模拟实现string

string时STL中的模板库之一&#xff0c;类似于专门处理字符串的数据结构&#xff0c;在模拟实现并探讨其中构造的巧妙之处之前&#xff0c;我们短浅的认识一下STL是什么 目录 什么是STL STL的诞生 关于string string的模拟实现 构造函数和析构函数 实现简单的string打印 …

【蓝桥杯】简单数论2——快速幂矩阵快速幂

1、快速幂 1.1运算模 定义&#xff1a;模运算为a除以m的余数&#xff0c;记为a mod m&#xff0c;有a mod m a % m。 模运算是大数运算中的常用操作&#xff1a;如果一个数太大&#xff0c;无法直接输出&#xff0c;或者不需要直接输出&#xff0c;可以把它取模后&#xff0…

Android 深入系统完全讲解(37)

7.5 源码讲解 dlopen 打开动态库 dlsym 找到符号 (*print_func)(); 调用方法 我们可以看到&#xff0c;要使用一个 so 库的某个方法&#xff0c;就上面三步骤&#xff0c;加载 &#xff0c;查找 &#xff0c;使用 。我 们这里调用了 so 库中的 my_print 方法。 7.6 运行 我们把…

Linux——进程间通信

文章目录前言1. 进程间通信方式的一些标准&#xff1a;2. 管道2.1 什么是管道2.2 管道的原理2.3 匿名管道2.3.1 实例代码1. demo代码2. 总结管道的特点&#xff0c;理解以前的管道 |3. 扩展——进程池2.4 管道读写规则2.5 命名管道2.5.1 创建一个命名管道2.5.2 命名管道的打开规…