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('事件名')
相关推荐
_揽8 分钟前
html如何在一张图片上的某一个区域做到点击事件
前端·html
踢足球的,程序猿11 分钟前
从 Vue 2.0 进阶到 Vue 3.0 的核心技术解析指南
前端·javascript·vue.js·前端框架·html
冷凌爱12 分钟前
Fetch与Axios:区别、联系、优缺点及使用差异
前端·node.js·js
袁煦丞34 分钟前
跨平台终端王者Tabby:cpolar内网穿透实验室第632个成功挑战
前端·程序员·远程工作
Sailing36 分钟前
Grafana-mcp-analyzer:基于 MCP 的轻量 AI 分析监控图表的运维神器!
前端·node.js·mcp
阿山同学.1 小时前
AWS 亚马逊 S3存储桶直传 前端demo 复制即可使用
前端·javascript·aws
Jolyne_1 小时前
grid 实现完美的水平铺满、间隔一致的自适应布局
前端·css
sunly_1 小时前
Flutter:导航固定背景图,滚动时导航颜色渐变
android·javascript·flutter
西洼工作室1 小时前
【解决导航栏字体图标渲染导致文本闪烁问题】采用腾讯视频的解决方案
前端·css·css3
摸鱼仙人~1 小时前
深入理解Java单例模式:确保类只有一个实例
java·javascript·单例模式