1. 程式人生 >實用技巧 >其它 >vue 訊息匯流排解耦 bus.$on(), bus.$emit(), bus.$off

vue 訊息匯流排解耦 bus.$on(), bus.$emit(), bus.$off


  1. bus 是一個 Vue 物件
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
    <style>
        .part {
            position: absolute;
            height: 300px;
            width: 300px;
        }
    </style>
</head>

<body>
    <div id='app'>
        <part1 style="top: 10px; background-color: lightskyblue;" class="part"></part1>
        <part2 style="top: 200px; left: 320px; background-color: lightsteelblue;" class="part"></part2>
    </div>
    <script>
        const bus = new Vue();

        const Part1VM = {
            template: `
            <div>
                <input v-model="msg" />
                <button @click="send">傳送</button>
                <button @click="abort">中止</button>
            </div>`,
            data() {
                return {
                    msg: ''
                };
            },
            methods: {
                send() {
                    bus.$emit('message', this.msg);
                },
                abort() {
                    bus.$off('message');
                }
            }
        };

        Vue.component('part1', Part1VM);

        const Part2VM = {
            template: `
            <div>
                <input v-model="msg" />
            </div>`,
            data() {
                return {
                    msg: ''
                };
            },
            mounted() {
                bus.$on('message', (msg) => {
                    this.msg = msg;
                })
            }
        };
        
        Vue.component('part2', Part2VM);

        const app = new Vue({
            el: '#app',
        });
    </script>
</body>

</html>
  1. 隨便仿寫一個
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
    <style>
        .part {
            position: absolute;
            height: 300px;
            width: 300px;
        }
    </style>
</head>

<body>
    <div id='app'>
        <part1 style="top: 10px; background-color: lightskyblue;" class="part"></part1>
        <part2 style="top: 200px; left: 320px; background-color: lightsteelblue;" class="part"></part2>
    </div>
    <script>

        class Bus {
            constructor() {
                this.eventDict = {};  // {msg: callback, log: callback2}
            }

            on(event, callback) {
                this.eventDict[event] = callback;
            }

            emit(event, ...params) {
                if (!(event in this.eventDict)) {
                    return;
                }
                let callback = this.eventDict[event];
                callback(...params);  // ... 在此處表示陣列轉可變引數
            }

            off(event) {
                if (event in this.eventDict) {
                    delete this.eventDict[event];
                }
            }

        }

        const bus = new Bus();

        const Part1VM = {
            template: `
            <div>
                <input v-model="msg" />
                <button @click="send">傳送</button>
                <button @click="abort">中止</button>
            </div>`,
            data() {
                return {
                    msg: ''
                };
            },
            methods: {
                send() {
                    bus.emit('message', this.msg);
                },
                abort() {
                    bus.off('message');
                }
            }
        };

        Vue.component('part1', Part1VM);

        const Part2VM = {
            template: `
            <div>
                <input v-model="msg" />
            </div>`,
            data() {
                return {
                    msg: ''
                };
            },
            mounted() {
                bus.on('message', (msg) => {
                    this.msg = msg;
                })
            }
        };

        Vue.component('part2', Part2VM);

        const app = new Vue({
            el: '#app',
        });
    </script>
</body>

</html>