从VueJS组件发出重复事件

use*_*888 7 javascript event-bus vue.js vuejs2 vue-devtools

当我的鼠标光标进入并离开我的VueJS组件时,分别调用以下方法.

光标进入和离开组件时调用的方法:

// located in "methods" section of my Vue component file

onMouseEnter() {
    window.Event.$emit("mouse-entered", this.index);
    console.log("Mouse entered");
},
onMouseLeave() {
    window.Event.$emit("mouse-left", this.index);
    console.log("Mouse left");
},
Run Code Online (Sandbox Code Playgroud)

预计,当我的光标进入并离开组件时,这就是我的控制台的样子(每次发出一个事件):

在此输入图像描述

然而,真正奇怪的是,在Vue开发工具中,我看到每次光标进入并离开组件时都会发出重复事件:

在此输入图像描述

鉴于这种相互矛盾的信息,我不确定该相信什么.刷新页面有时会消除开发工具中的重复事件,但我总是在我的控制台中获得单个唯一的事件,这是我想要的行为.

有谁知道这里发生了什么,我应该接受什么作为真相的来源?

下面是我的main.js文件中声明和初始化我的Vue实例的方法:

// As far as I can tell, duplicated Vue instances are not being created here on page refresh

let app;

// global event bus
window.Event = new Vue();
console.log("Event bus created");

/* This section ensures the firebase auth object isn't in an intermediary state. */
firebase.auth().onAuthStateChanged(() => {
    if (!app) {
        console.log("New Vue instance created");
        app = new Vue({
            el: '#app',
            router,
            store,
            render: h => h(App)
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

请注意,此特定组件正在两个不同的路由("仪表板"和"主页")上重用,这两个路由都通过以下代码保持活动状态.

// Template section of App.vue file
<template>
    <div id="app">
        <keep-alive
            v-bind:include="[ 'dashboard', 'home' ]"
            <router-view></router-view>
        </keep-alive>
    </div>
</template>
Run Code Online (Sandbox Code Playgroud)

另外,由于这两条路由保持活动和缓存,因此不能将$ off关闭事件发送器和监听器不应该是重复的原因(至少我认为不应该).

编辑1:我在项目的每个目录中都找到了"鼠标输入"和"鼠标左键"的全部内容,我可以确认这两个事件都是从我在本文中引用的Vue组件中发出的.

编辑2:为了帮助调试,我将一个监听器放在我最顶层的组件(App.vue)上,看看它是否收到了两次事件(请参阅下面代码片段中创建的钩子).我可以确认它也只收到一次事件.我也粘贴在我完整的App.vue文件中,因为上面的例子主要是为了说明我保持"仪表板"和"主页".

<template>
    <div id="app">
        <keep-alive
            v-bind:include="keepAlive">
            <router-view></router-view>
        </keep-alive>
    </div>
</template>

<script>
    export default {
        name: 'app',
        data() {
            return {
                isLoggedIn: false,
            };
        },
        computed: {
            keepAlive() {
                if (this.isLoggedIn) {
                    return [ 'dashboard', 'home', 'results' ];
                }
                return [ 'landing', 'signIn', 'signUp' ];
            }
        },
        watch: {
            /* This watches for route changes */
            $route(to, from) {
                /* firebase.auth().currentUser returns null if user has logged out */
                if (firebase.auth().currentUser) {
                    this.isLoggedIn = true;
                } else {
                    this.isLoggedIn = false;
                }
            }
        },
        created() {
            window.Event.$on("mouse-entered", () => {
                console.log("mouse-entered-from-App.vue");
            });
            window.Event.$on("mouse-left", () => {
                console.log("mouse-left-from-App.vue");
            });
        }
    };
</script>
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,App.vue会收到一次事件(见下文); 但是,我仍然在Vue dev工具中获得重复事件:(

在此输入图像描述

van*_*jor 6

你写了

刷新页面有时会消除开发工具中的重复事件,但我总是在控制台中获得单个、独特的事件,这是我想要的行为。

您描述问题的方式,事件是正确发出的,而它们却以错误的、重复的方式做出反应。我认为您可能缺少的是一旦组件被破坏就取消订阅您的事件总线。您应该使用beforeDestroy钩子来执行此操作(类似于您created之前在组件生命周期中使用的订阅方式)。

像这样的东西:

beforeDestroy() {
    window.Event.$off('mouse-entered');
    window.Event.$off('mouse-left');
}
Run Code Online (Sandbox Code Playgroud)