最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Duplicate events being emitted from VueJS component - Stack Overflow

programmeradmin4浏览0评论

When my mouse cursor enters and leaves my VueJS ponent, the following methods are called respectively.

Methods that are called when the cursor enters and leaves my ponent:

// located in "methods" section of my Vue ponent 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");
},

Expectedly, this is what my console looks like when my cursor enters and leaves the ponent (one event is emitted each time):

However, what's really strange is that in Vue dev tools, I'm seeing duplicate events being emitted every time my cursor enters and leaves my ponent:

Given this conflicting information, I'm not sure what to believe. Refreshing the page sometimes eliminates the duplicate events in dev tools but I always get single, unique events in my console, which is my desired behaviour.

Does anyone know what is happening here and what should I accept as the source of truth?

Below is how my Vue instances are being declared and initialised in my main.js file:

// 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)
        });
    }
});

Note that this particular ponent is being reused on two different routes( "dashboard" and "home" ), which are both being kept alive by the following code.

// 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>

Additionally, since those two routes are being kept alive and cached, failure to turn $off event emitters and listeners should not be the cause of duplication (at least I think it shouldn't).

EDIT 1: I did a find all for "mouse-entered" and "mouse-left" in every single directory in my project and I can confirm that both events are only emitted from the Vue ponent I've referenced to in this post.

EDIT 2: To help with debugging, I put a listener on my top-most ponent (App.vue) to see if it receives the event twice (refer to the created hook in the code snippet below). I can confirm it also only receives the event once. I've also pasted in my plete App.vue file since the above example was mainly to illustrate that I'm keeping alive "dashboard" and "home".

<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,
            };
        },
        puted: {
            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>

As expected, App.vue receives the event once (see below); however, I'm still getting duplicate events in Vue dev tools :(

When my mouse cursor enters and leaves my VueJS ponent, the following methods are called respectively.

Methods that are called when the cursor enters and leaves my ponent:

// located in "methods" section of my Vue ponent 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");
},

Expectedly, this is what my console looks like when my cursor enters and leaves the ponent (one event is emitted each time):

However, what's really strange is that in Vue dev tools, I'm seeing duplicate events being emitted every time my cursor enters and leaves my ponent:

Given this conflicting information, I'm not sure what to believe. Refreshing the page sometimes eliminates the duplicate events in dev tools but I always get single, unique events in my console, which is my desired behaviour.

Does anyone know what is happening here and what should I accept as the source of truth?

Below is how my Vue instances are being declared and initialised in my main.js file:

// 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)
        });
    }
});

Note that this particular ponent is being reused on two different routes( "dashboard" and "home" ), which are both being kept alive by the following code.

// 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>

Additionally, since those two routes are being kept alive and cached, failure to turn $off event emitters and listeners should not be the cause of duplication (at least I think it shouldn't).

EDIT 1: I did a find all for "mouse-entered" and "mouse-left" in every single directory in my project and I can confirm that both events are only emitted from the Vue ponent I've referenced to in this post.

EDIT 2: To help with debugging, I put a listener on my top-most ponent (App.vue) to see if it receives the event twice (refer to the created hook in the code snippet below). I can confirm it also only receives the event once. I've also pasted in my plete App.vue file since the above example was mainly to illustrate that I'm keeping alive "dashboard" and "home".

<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,
            };
        },
        puted: {
            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>

As expected, App.vue receives the event once (see below); however, I'm still getting duplicate events in Vue dev tools :(

Share Improve this question edited Jul 22, 2018 at 3:10 ptk asked Jul 21, 2018 at 14:49 ptkptk 7,65317 gold badges53 silver badges106 bronze badges 5
  • That's definitely odd. Perhaps unnecessary, but have you double-checked that you don't have any mouse-entered events somewhere else in your code without a console.log that could be triggered somehow? Are you able to consistently get this behaviour by navigating? Or is editing and saving your code involved? – Sumurai8 Commented Jul 21, 2018 at 15:20
  • @Sumurai8 I can confirm that the events are never emitted from other ponents after doing a find all in my project's directories. It consistently happens when I navigate to other routes and back to the routes (dashboard and home) that this ponent resides on. Also the events only ever duplicate, never more. – ptk Commented Jul 21, 2018 at 15:54
  • 1 I can't really think of a situation where the event would fire, but the console message would not be duplicated, so you could try to put a listener on your top-most ponent and see if that receives the event twice. If it doesn't, I think it is safe to say that the vue devtools have a bug. Otherwise we need to look further. – Sumurai8 Commented Jul 21, 2018 at 21:08
  • @Sumurai8 I've put a listener on App.vue and I can confirm that it only receives the event once but I still get duplicate events emitted in dev tools. I've also added my entire App.vue code, which looks ok to me but might reveal something to others. – ptk Commented Jul 22, 2018 at 3:12
  • 1 as long as the event is effectively only triggered once (e.g. console logging) it shouldn't matter what is displayed in the dev tools, your program should work. doesn't it? .. this might be a bug in the vue-devtools. some hidden event bubbling maybe? – товіаѕ Commented Oct 3, 2018 at 12:31
Add a ment  | 

1 Answer 1

Reset to default 6

You wrote

Refreshing the page sometimes eliminates the duplicate events in dev tools but I always get single, unique events in my console, which is my desired behaviour.

The way you describe your problem, the events are emitted correctly, while they are being reacted on in a wrong, duplicate way. I think what you might be missing is unsubscribing from your event bus once the ponent gets destroyed. You should use the beforeDestroy hook to do so (similar to the way you used created earlier on in the ponent's lifecycle to subscribe).

Something like this:

beforeDestroy() {
    window.Event.$off('mouse-entered');
    window.Event.$off('mouse-left');
}
发布评论

评论列表(0)

  1. 暂无评论