Monday, June 4, 2018

[Vue.js][Resolved] "TypeError: Cannot read property '$on' of undefined" when using global event bus

Error Msg:
vue.esm.js?efeb:591 [Vue warn]: Error in mounted hook: "TypeError: Cannot read property '$on' of undefined"
found in
---> <App> at src/App.vue
       <Root>


warn @ vue.esm.js?efeb:591
logError @ vue.esm.js?efeb:1737
globalHandleError @ vue.esm.js?efeb:1732
handleError @ vue.esm.js?efeb:1721
callHook @ vue.esm.js?efeb:2923
insert @ vue.esm.js?efeb:4158
invokeInsertHook @ vue.esm.js?efeb:5960
patch @ vue.esm.js?efeb:6179
Vue._update @ vue.esm.js?efeb:2660
updateComponent @ vue.esm.js?efeb:2788
get @ vue.esm.js?efeb:3142
Watcher @ vue.esm.js?efeb:3131
mountComponent @ vue.esm.js?efeb:2795
Vue.$mount @ vue.esm.js?efeb:8540
Vue.$mount @ vue.esm.js?efeb:10939
Vue._init @ vue.esm.js?efeb:4640
Vue @ vue.esm.js?efeb:4729
(anonymous) @ main.js?3479:7
(anonymous) @ build.js:751
__webpack_require__ @ build.js:679
fn @ build.js:89
(anonymous) @ build.js:835
__webpack_require__ @ build.js:679
(anonymous) @ build.js:725
(anonymous) @ build.js:728
vue.esm.js?efeb:1741 TypeError: Cannot read property '$on' of undefined
    at VueComponent.mounted (App.vue?ea99:19)
    at callHook (vue.esm.js?efeb:2921)
    at Object.insert (vue.esm.js?efeb:4158)
    at invokeInsertHook (vue.esm.js?efeb:5960)
    at Vue.patch [as __patch__] (vue.esm.js?efeb:6179)
    at Vue._update (vue.esm.js?efeb:2660)
    at Vue.updateComponent (vue.esm.js?efeb:2788)
    at Watcher.get (vue.esm.js?efeb:3142)
    at new Watcher (vue.esm.js?efeb:3131)
    at mountComponent (vue.esm.js?efeb:2795)
I created a global event bus and find I can't use the $on method of mounted hook
main.js
import Vue from 'vue'
import App from './App.vue'
import Student from './Student.vue'

Vue.component("student", Student);

new Vue({
  el: '#app',
  render: h => h(App)
});

export const EventBus = new Vue();
App.vue
<template>
    <div id="app">
        <student></student>
        <hr />
        <p>Parent value: {{gname}}</p>
    </div>
</template>

<script>
   import {EventBus} from "./main.js"

   export default {
     data(){
       return {gname : "#"}
     },
     mounted(){
         var self = this;
         console.log(EventBus);
         EventBus.$on("sname",function(data){
            self.ganame = data;
         });
     }
   }
</script>
Student.vue
<template>
    <div>
        <h2>Student</h2>
        <p>Student name : {{name}} <button @click="updateName">update</button></p>
    </div>
</template>

<script>
   import {EventBus} from "./main.js"
   export default {
        data:function(){
            return {
                "name":"@",
                };
        },
        methods:{
            updateName(e){
                this.name = "Ann";
                EventBus.$emit("sname","Ann");
            },
        }
   }
</script>

finally I found the error is cause by the position of the global event bus code, you should place it before the vue instances, for example:

import Vue from 'vue'
import App from './App.vue'
import Student from './Student.vue'

export const EventBus = new Vue();

Vue.component("student", Student);

new Vue({
  el: '#app',
  render: h => h(App)
});


Reference

https://alligator.io/vuejs/global-event-bus/

1 comment :