search

Home  >  Q&A  >  body text

vue.js using public event bus - Stack Overflow

While practicing the use of the vue framework and writing a todo demo, I put the input element (new-input component) and the ul and li elements ( todo-items and todo-item components) are written as two parallel components. Now enter text to add in the input component, use the public event bus to trigger the update event, and create a hook function in the life cycle of the todo-items component to listen to the update event and Modify the data in the component, and then the problem comes. The error message shows that the todos array of the component is undefined

#Post the code below

var bus = new Vue({});

var todoItem = Vue.component('todo-item', {
    props:['todo'],
    template:'<li class="animated fadeIn cusFont" v-bind:class="{ done:isDone }"><span><button class="done" v-on:click="done" v-bind:class="{doneButton: isDone}"></button></span><p v-bind:class="{doneItem:isDone}">{{todo.text}}</p><button class="delete" v-on:click="deleteIt">×</button></li>',
    data:function(){
        return {
            isDone:false
        }
    },
    methods:{
        done:function(){
            this.$emit('hasDone');
            this.isDone = !this.isDone;
        },
        deleteIt:function(){
            this.$emit('hasDelete');
        }
    }    
});
var todoItems = Vue.component('todo-items', {
    template:'<ul><todo-item v-for="(item, index) in todos" v-bind:todo="item" v-on:hasDelete="deleteItem(index)"></todo-item></ul>',
    data:function(){
        return {
            todos:[
                {text:'nodeJS'},
                {text:'vue.js'}
            ]
        }
    },
    components:{
        'todo-item':todoItem
    },
    methods:{
        deleteItem:function(index){
            this.todos.splice(index, 1);
        },
        update:function(value){
            this.todos.push(value);
        }
    },
    created(){
        bus.$on('updateData', function(value){
            this.todos.push(value);
        })
    }
})

var newInput = Vue.component('new-input', {
    template:'<input ref="input" placeholder="What needs to be done?" id="js-input-item" v-bind:value="value" class="animated fadeIn cusFont" v-on:keyup.enter="update">',
    data:function(){
        return {
            value:''
        }
    },
    methods:{
        update:function(){
            bus.$emit('updateData', {text:this.$refs.input.value});
        }
    }
})

var todo = new Vue({
    el:'#todo',
    components:{
        "todo-items":todoItems,
        "new-input":newInput
    }
})

For some unknown reason, the deleteItem method in todo-items can also operate the todos array.

黄舟黄舟2803 days ago951

reply all(2)I'll reply

  • typecho

    typecho2017-06-12 09:27:35

    Answer on mobile
    The problem mainly occurs in bus.$emit. Bus is a new instance of Vue, and its this has no todos. It should be like this

    Inside

    created:
    const that = this
    Afterwards, this inside bus is changed to that

    Answer on mobile phone, I won’t write detailed code, you should understand

    reply
    0
  • 世界只因有你

    世界只因有你2017-06-12 09:27:35

    This in the callback function monitored by the bus instance does not point to the vue instance you expected. The solution is as mentioned above

    reply
    0
  • Cancelreply