Hot questions for Using EventBus in javascript

Question:

Basically I want to be able to access some centralized data by setting up a dataBus as a vue instance object, and then access and tweak this data from different components.

I cant seems to access by data from my componenets, even basic string interpolation is not getting rendered to the DOM.

  export const dataBus = new Vue({
    data: {
      numQuotes: 4,
      stringVar: 'Hellow There'
    }
  });

I also tried setting up my data as the return of the function data(). But being as my data bus is an actual vue instance I don't think this is correct. (I could be wrong). Following is the component in which I import my dataBus and try to output my data.

  <template>
    <div>
      <h1>Quotes Added</h1>
      <div id="trackerBar">
        <div id="trackerBarActual">
            <h2>{{numQuotes}}/10</h2>
        </div>
      </div>
    </div>

  </template>

  <script>
    import { dataBus } from '../main.js';

    export default{

    }
  </script>

I am getting the following error: Property or method "numQuotes" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.

Am I missing something obvious? Is it even possible to access data this way? Or do I have to access it as a method?


Answer:

You're missing the part where you assign data to your component. Try

<script>
import { dataBus } from '../main.js';

export default{
  data () {
    return dataBus.$data
  }
}
</script>

You should definitely look into Vuex for state management though.

Question:

When i click a button, i want to subscribe to an event

EventBus.subscribe("sChannelFoo", "sIdBar", function(){
alert("FOOBAR!");
});

I subscribe on "sChannelFoo" and sIdBar" throughout my code. What is a neat solution to make sure that I subscribe to this event only once with this button, even if I click my button several times?

If I have 1000 other buttons, I want them to also be able to subscribe exactly once to "sChannelFoo" and "sIdBar". The other 1000 buttons may have the same function or a different one.


Answer:

You could use the method attachEventOnce on your Button control: https://openui5.hana.ondemand.com/docs/api/symbols/sap.ui.base.EventProvider.html#attachEventOnce

With the registered handler function you can invoke the subscription to the event bus:

oButton.attachEventOnce('press', function() {
    EventBus.subscribe("sChannelFoo", "sIdBar", function() {
        alert(FOOBAR!");
     });
}

Question:

I'm working on a vue single page project,and I use an empty Vue instance as a central event bus.But there is some problem when firing a event.

eventbus.js

import vue from 'Vue'
export default new vue({})

a.vue

import bus from '~js/eventBus'
methods: {
    go(name) {
        bus.$emit('setPartner', name);
            this.$router.go(-1);
    }
}

b.vue

import bus from '~js/eventBus'
data() {
         return {
           contract: {
               contractSubject: ''
           }
         }
     },
mounted(){

     bus.$once('setPartner', data => {
          this.contract.contractSubject = data;
     });
}

in b.vue file,I can recieve data,but I can't assign the value of data to 'this.contract.contractSubject'


Answer:

I would comment, but point restrictions. It seems like you're only posting snippets of the code, so it's hard to get a full picture. I assume that you've already set this.contract to be an Object? I don't know what your data function looks like, and an error message would be helpful, but it sounds like you're trying to assign a field on an object that doesn't exist yet.

Edit

Thanks for the information. I'm not sure if your edit to b.vue was a mistake when you copied things over to stackoverflow, but based on the code you've provided, my guess is that you wrote data() in the wrong place. You have it inside mounted(), not as a key value of the component object, and thus this.contract won't access it.

I managed to get it working under the setup below

a.vue

import bus from './bus.js';

export default {
  name: 'sitea',
  methods: {
    go(name) {
      bus.$emit('setPartner', name);
    }
  }
}

b.vue

import bus from './bus.js'

export default {
  name: 'siteb',
  data() {
    return {
      contract: {
        contractSubject: ''
      }
    }
  },
  mounted() {
    bus.$once('setPartner', data => {
      console.log(data);
      this.contract.contractSubject = data;
    });
  }
}

More information