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('事件名')
相关推荐
开心工作室_kaic15 分钟前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿34 分钟前
webWorker基本用法
前端·javascript·vue.js
cy玩具1 小时前
点击评论详情,跳到评论页面,携带对象参数写法:
前端
清灵xmf1 小时前
TypeScript 类型进阶指南
javascript·typescript·泛型·t·infer
小白学大数据1 小时前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
qq_390161772 小时前
防抖函数--应用场景及示例
前端·javascript
334554322 小时前
element动态表头合并表格
开发语言·javascript·ecmascript
John.liu_Test2 小时前
js下载excel示例demo
前端·javascript·excel
Yaml42 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事2 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro