使用发布订阅者模式实现组件间通信

vue2 组件间通信代码

在 vue2 里面,遇到 组件间通信的时候一般我会用到如下代码

1
2
3
4
// channel.js
import Vue from "vue";

export default new Vue();
1
2
3
4
5
6
7
8
9
10
11
// A.vue
<script>
import channel from "./channel.js"
export default {
mounted() {
channel.$on("btnClick", () => {
console.log('xxx')
});
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// B.vue
<template>
<div>
<button @click="handleBtnClick" value="click"/>
</div>
</template>

<script>
import channel from "./channel.js"
export default {
methods: {
handleBtnClick: function() {
channel.$emit('btnClick')
}
}
}
<script>

而在 vue3 里面,可以借助另外的工具,比如 tiny-emitter

1
2
3
4
5
6
// eventBus.ts
const Emitter = require('tiny-emitter');

const emitter = new Emitter();

export default emitter;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// A.vue
<script lang="typescript">
import { defineComponent, unmount } from 'vue'
import eventBus from "./eventBus.ts"

export default defineComponent({
unmount() {
eventBus.on("btnClick");
},
setup() {
eventBus.on("btnClick", () => {
console.log('xxx')
});
}
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// B.vue
<template lang="typescript">
<div>
<button @click="handleBtnClick" value="click"/>
</div>
</template>

<script>
import { defineComponent } from 'vue'
import eventBus from "./eventBus.ts"

export default defineComponent({
setup() {
const handleBtnClick = () => {
eventBus.emit('btnClick')
}

return {
handleBtnClick
}
}
})

<script>

手动实现

但是最近读到《JavaScript设计模式与开发实际》这本书,里面提到发布订阅者模式(也叫观察者模式),就想到了组件间通信的场景,现在就来尝试实现一下

具体代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// eventBus.js
let eventBus = function() {
let eventList = {}

// 订阅者
function on(key, fn) {
if (!eventList[key]) {
eventList[key] = []
}
eventList[key].push(fn)
}

// 发布者
function emit() {
let key = Array.prototype.shift.call(arguments)
let fnList = eventList[key]
if (!fnList || fnList.length === 0) {
return false
}
fnList.forEach(fnItem => {
fnItem.apply(null, arguments)
})
}

function remove(key, fn) {
let fnList = eventList[key]
if (!fnList) {
return
}
if (fn) {
const len = fnList.length
for(let i = len; i >= 0; i--) {
let _fn = fnList[i]
if (_fn === fn) {
fnList.splice(i, 1)
}
}
} else {
fnList && (fnList.length = 0)
}
}

return {
on,
emit,
remove
}

}()


module.exports = eventBus

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// test.js

const eventBus = require('./eventBus')

let ssFn = function(a, b) {
console.log(a)
console.log(b)
}

eventBus.on('ss', ssFn)

eventBus.emit('ss', 123, 34) // 123 // 34

eventBus.remove('ss', ssFn)

eventBus.emit('ss', 123, 34) // null

代码:https://github.com/allenliu123/StudyCode/tree/main/Eventer

文章作者: Allen Lau
文章链接: https://blog.ifthat.com/event-bus/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 A.Lau's Blogs