Vue2&3全局事件总线

Vue2&3全局事件总线

Vue2全局事件总线

  • 功能:可以解决所有组件之间通信传数据的问题
  • 原理:通过一个共享对象,将所有组件全部绑定到对象上,即可通过这个对象实现组件与组件之间的传递数据,而这个共享对象叫做全局事件总线。

如何分清楚谁是发送方,谁是接收方?谁用绑定事件,谁用触发事件?

  • 假设:我向你传送数据,我是发送方,你是接收方。
    • 若我不向你发送数据,则你就不知道数据的内容,无法拿取(绑定)。(我不触发,你不能绑定,因为你没有数据)
    • 只有我发送数据给你,你才能知道数据的内容,才能对数据进行拿取。(谁发送谁触发,谁拿取谁绑定)

共享对象创建位置:main.js文件

  • 第一种方法:创建vc对象
javascript 复制代码
// 获取 VueComponent 构造函数
const VueComponentConstructor = Vue.extend({})
// 创建 vc 对象
const vc = new VueComponentConstructor()
// 使所有组件共享 vc 对象
Vue.prototype.$bus = vc
  • 第二种方法(常用):使用原有的vm对象
    • 在Vue初始化时(beforeCreate),创建共享对象vm
javascript 复制代码
new Vue({
  el : '#app',
  render: h => h(App),
  beforeCreate(){
    // this指向的是vm
    Vue.prototype.$bus = this
  }
})

以上代码中出现的$bus有什么作用?

  • $bus:事件总线,用来管理总线。
  • 其他组件在调用vc共享对象时可通过this.$bus.$on()this.$bus.$emit()来绑定或触发事件

数据发送方:触发事件$emit

  • 触发事件:this.$bus.$emit('事件名', 接受的数据)
javascript 复制代码
// Vip.vue
<template>
    <div>
        <button @click="triggerEvent">触发事件</button>
    </div>
</template>

<script>
    export default {
        name : 'Vip',
        data(){
            return{
                name : 'zhangsan'
            }
        },
        methods : {
            triggerEvent(){
                this.$bus.$emit('event', this.name)
            }
        }
    }
</script>

数据接收方:绑定事件$on

  • 绑定事件:this.$bus.$on('事件名', 回调函数)
javascript 复制代码
// App.vue
<template>
    <div>
        <Vip></Vip>
    </div>
</template>

<script>
    import Vip from './components/Vip.vue'
    export default {
        name : 'App',
        mounted() {
            this.$bus.$on('event', this.test)
        },
        methods : {
            test(name){
                console.log(name);
            }
        },
        components : {Vip}
    }
</script>

Vue3全局事件总线

安装mitt

  • 在CMD窗口中,跳转到Vue3安装路径下
  • 输入命令npm i mitt,当出现up to date in 595ms等类似信息表示安装成功

使用mitt(只要使用全局事件总线,所在的组件就要引入emitter)

  • 第一步:创建一个文件夹utils,在文件夹中创建js文件(event-bus.js)
  • 第二步:在js文件中导入并暴露mitt(如下)
    • 这里的操作主要是为了生成对象emitter
javascript 复制代码
// utils/event-bus.js
import mitt from 'mitt'

// mitt函数的执行会生成一个对象:emitter对象
// emitter对象是一个全局事件总线对象
// 绑定和触发的操作都在这个对象上的完成
export default mitt()

实现绑定与触发事件

  • 绑定事件:emitter.on('事件名', 回调函数)
  • 触发事件:emitter.emit('事件名', 接收的数据)
javascript 复制代码
// App.vue
<template>
    <Info></Info>
</template>

<script>
    // 引入全局事件总线对象
    import emitter from './utils/event-bus.js'
    import Info from './components/Info.vue'
    // 引入组合式API:生命周期钩子
    import { onMounted } from 'vue'
    export default {
        name : 'App',
        components : {Info},
        setup(){
            // 生命周期钩子:onMounted
            onMounted(() => {
                // 绑定事件
                emitter.on('event1', showInfo)
            })
            
            function showInfo(info){
                alert(`姓名:${info.name}`)
            }

            return {showInfo}
        }
    }
</script>
javascript 复制代码
// Info.vue
<template>
    <button @click="triggerEvent1">触发event1事件</button>
</template>

<script>
    // 导入全局事件总线对象
    import emitter from '../utils/event-bus.js'
    export default {
        name : 'Info',
        setup(){
            function triggerEvent1(){
                // 触发事件
                emitter.emit('event1', {name:'jack'})
            }
            
            return {triggerEvent1}
        }
    }
</script>

解绑事件

  • 原理:在子组件中使用 off 可以消除指定的事件
  • 解绑事件:emitter.off('事件名')
javascript 复制代码
// Info.vue
<template>
    <button @click="triggerEvent1">触发event1事件</button>
    <br>
    <button @click="clearEvent1">解绑event1事件</button>
</template>

<script>
    // 引入入全局事件总线对象
    import emitter from '../utils/event-bus.js'
    export default {
        name : 'Info',
        setup(){
            function triggerEvent1(){
                // 触发全局事件总线上的事件
                emitter.emit('event1', {name:'jack'})
            }

            function clearEvent1(){
                // 解绑指定的事件
                emitter.off('event1')
            }
            
            return {triggerEvent1, clearEvent1}
        }
    }
</script>

Vue2和Vue3在触发和绑定上的不同

  • 第一点:引用的方式不同
javascript 复制代码
// Vue2 的 main.js
new Vue({
  el : '#app',
  render: h => h(App),
  beforeCreate(){
    Vue.prototype.$bus = this
  }
})

// Vue3 的 utils/event-bus.js
import mitt from 'mitt'
export default mitt()
  • 第二点:调用方式的不同
javascript 复制代码
// Vue2
绑定:this.$bus.$on('事件名', 回调函数)
触发:this.$bus.$emit('事件名', 接受的数据)
解绑:this.$bus.$off('事件名')

// Vue3 需要先引入 import emitter from '../utils/event-bus.js'
绑定:emitter.on('事件名', 回调函数)
触发:emitter.emit('事件名', 接收的数据)
解绑:emitter.off('事件名')
JavaScript
// Vue2
绑定:this.$bus.$on('事件名', 回调函数)
触发:this.$bus.$emit('事件名', 接受的数据)
解绑:this.$bus.$off('事件名')

// Vue3 需要先引入 import emitter from '../utils/event-bus.js'
绑定:emitter.on('事件名', 回调函数)
触发:emitter.emit('事件名', 接收的数据)
解绑:emitter.off('事件名')
相关推荐
敲敲了个代码4 小时前
从硬编码到 Schema 推断:前端表单开发的工程化转型
前端·javascript·vue.js·学习·面试·职场和发展·前端框架
dly_blog6 小时前
Vue 响应式陷阱与解决方案(第19节)
前端·javascript·vue.js
消失的旧时光-19436 小时前
401 自动刷新 Token 的完整架构设计(Dio 实战版)
开发语言·前端·javascript
console.log('npc')6 小时前
Table,vue3在父组件调用子组件columns列的方法展示弹窗文件预览效果
前端·javascript·vue.js
用户47949283569156 小时前
React Hooks 的“天条”:为啥绝对不能写在 if 语句里?
前端·react.js
我命由我123457 小时前
SVG - SVG 引入(SVG 概述、SVG 基本使用、SVG 使用 CSS、SVG 使用 JavaScript、SVG 实例实操)
开发语言·前端·javascript·css·学习·ecmascript·学习方法
用户47949283569157 小时前
给客户做私有化部署,我是如何优雅搞定 NPM 依赖管理的?
前端·后端·程序员
C_心欲无痕7 小时前
vue3 - markRaw标记为非响应式对象
前端·javascript·vue.js
qingyun9897 小时前
深度优先遍历:JavaScript递归查找树形数据结构中的节点标签
前端·javascript·数据结构
胡楚昊7 小时前
NSSCTF动调题包通关
开发语言·javascript·算法