简体   繁体   中英

Why cant' I trigger custom events in vue.js?

I have a local database that will be updated with pusher. This database is stored in JSON and the component will load and filter out what is not needed, making it impossible to add a watcher to the raw data.

My idea (please advice me if there are better solution) was to add a listener for a custom event, then trigger this event when the DB is updated. The only event I'm able to trigger is 'CLICK', with a simple $('.vue-template').trigger('click');

This is paired with a simple @click="doSomething" on the element I chose as my target.

This is not ideal because I don't want to fetch the data on any click, but only when the DB is updated, so I've tried @customevent="doSomething" but it doesn't work

Any help?

EDIT: More code

<template>
    <div class="listen listen-database-teachers"
         @dbupdate="testAlert">
        <span v-for="teacher in teachers"
              class="pointer btn btn-sm btn-default destroy-link"
              :data-href="computedHref(teacher)"
              :data-person="personIdentifier(teacher.person)"
              :data-personid="teacher.person_id">
        {{ personIdentifier(teacher.person) }} <span class="glyphicon glyphicon-remove"></span>
        </span>
    </div>
</template>

<script>
    export default {
        props: ['circleId'],
        data () {
            return {
                loading: false,
                teachers: null,
                error: null
            }
        },
        created () {
            // fetch the data when the view is created and the data is
            // already being observed
            this.fetchData();
        },
        methods: {
            fetchData() {
                this.error = this.teachers = this.categories = null;
                this.loading = true;

                var teachers = $(window).localDatabase('teachers', $(window).planner('currentSchoolId'));

                var searchCircle = this.circleId,
                    filtered_teachers = [];
                $.each(teachers, function(index, teacher){
                    if(teacher.membership_id == searchCircle)
                        filtered_teachers.push(teacher);
                });
                this.teachers = filtered_teachers.sort(function(a, b) {
                    return personIdentifier(a.person) > personIdentifier(b.person);
                });

                this.loading = false;
            },
            computedClass(teacher){
                return 'pointer btn btn-sm btn-default draggable membership-draggable-'+teacher.membership_id+' destroy-link'
            },
            computedHref(teacher){
                return window.links.destroy_membership
                        + '?association-id='+teacher.id
                        + '&circle-id='+teacher.circle_id;
            },
            testAlert: function(){
                return alert('success');
            }
        }
    }
</script>

EDIT 2: attempt to use BUS

Remember that I use Laravel Mix.

app.js

window.vue_bus = new Vue();

master.js

function handleDatabaseUpdate(){
    window.vue_bus.$emit('refresh-data');
}

component

created () {
        // fetch the data when the view is created and the data is
        // already being observed
        this.fetchData();
        window.vue_bus.$on('refresh-data', this.testAlert());
    },

I've isolated the relevant bits of the code. This executes testAlert() when the component is mounted, but it returns an error cbs[i] undefined when I call handleDatabaseUpdate() from browser console (on Firefox).

This is a case where I might use an event bus .

A bus is created by simply creating an empty Vue.

const bus = new Vue()

In whatever function you have outside that is dealing with the database, you can emit an event using the bus.

function handleDatabaseUpdate(){
   //do database things
   bus.$emit("refresh-data")
}

Then in your component, add a handler.

created(){
    bus.$on("refresh-data", this.fetchData)
}

Since it looks like you are using single file components, you will have to make the bus available to both the component and your database manager. You can do that two ways. Quick and dirty, expose the bus on the window.

window.bus = new Vue()

Second, you can create the bus in its own module and import the module into all the places you need to use it.

bus.js

import Vue from "vue"

const bus = new Vue()
export default bus;

And in the code that deals with the database and in your component, import the bus.

import bus from "/path/to/bus.js

That said, the reason you cannot listen to jQuery events in Vue is that jQuery uses it's own event system and Vue's listeners will never catch jQuery events. If you still wanted to use jQuery, you could emit a custom event in jQuery and listen to that custom event also using jQuery. You would just have to dispatch the event to fetchData.

created(){
    $("thing you sent the event from").on("refresh-data", this.fetchData)
}

Finally, this is also a case where a state management system (like Veux) would shine. State management systems are intended for cases like this where state could be changing in many places and automatically reflecting those changes in the view. There is, of course, more work implementing them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM