No More Posting New Topics!

If you have a question or an issue, please start a thread in our Github Discussions Forum.
This forum is closed for new threads/ topics.

Navigation

    Quasar Framework

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    Global Bus v Page Bus ?

    Framework
    1
    3
    639
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • R
      rab last edited by rab

      I’ve been using the global event bus to create decoupled components for a PWA.

      It works great until there are multiple instances of a page in the browsing history - each instance continues to receive and process events.

      Options

      1. Ignore it - just make sure event handlers are lightweight and idempotent.

      2. Introduce scope into the global bus (e.g. override $emit and $listen to prefix events with id of root component).

      3. Create a “page-bus” for each instance.

      4. Do something else.

      Any else had experience of this?

      R 1 Reply Last reply Reply Quote 0
      • R
        rab @rab last edited by rab

        @rab

        Keeping this here for posterity but no longer works in Vue 3.

        A solution that does work in Vue 3 is given in subsequent post (see reply below dated March 9th 2021).

        For anyone interested this works as a plugin solution. Please shout if you have a better approach or can contribute to improving this one; e.g.:

        1. Locating the page root is an educated guess and may not fit all cases.
        2. Desirable to use this.$page.$emit rather than this.$$emit.
        3. A better solution using Vue extends may exist.
        /* pagebus.js
        
        Using the global event bus to decouple components in a PWA works great
        until there are multiple copies of a page instance in the browsing history;
        each instance continues to receive and respond to events - especially
        troublesome when one of the components fetches data from the server
        (the data is fetched multiple times).
        
        An interim workaround is provided here by propagating events and listeners 
        to the 'page' root not the 'app' root.
        
        TO DO:
        
          1. Locating the page root is an educated guess and may not fit all cases.
          2. Desirable to use this.$page.$emit rather than this.$$emit.
          3. A better solution using Vue extends may exist.
        
        */
        
        import Vue from 'vue'
        
        const DEBUG = true
        
        export default {
          install (Vue, options) {
            Vue.mixin({
              methods: {
                $$page: function () {
                  // find the page root (educated guess)
                  let x = this;
                  do {
                    x = x.$parent;
                  } while (x && x.$parent && x.$parent.$parent !== x.$root);
                  return x
                },
                $$on: function (ev, ...args) {
                  // propagate to page root component
                  DEBUG && console.log('-> pagebus: on', this._uid, ev, args)
                  return (this.$$page() || this).$on(ev, ...args)
                },
                $$emit: function (ev, ...args) {
                  // propagate to page root component
                  DEBUG && console.log('-> pagebus: emit', this._uid, ev, args)
                  return (this.$$page() || this).$emit(ev, ...args)
                }
              }
            })
          }
        }
        
        R 1 Reply Last reply Reply Quote 0
        • R
          rab @rab last edited by rab

          @rab

          A Problem

          • Vue 3 instances no longer implement the event emitter interface.
          • Recommendation is to use mitt.
          • See: https://github.com/vuejs/rfcs/blob/master/active-rfcs/0020-events-api-change.md

          A Solution

          • Load the code below as a boot file (e.g. pagebus.js).
          • Using this.$on is detected as error so am using $$on instead.
          // file boot/pagebus.js
          import { boot } from 'quasar/wrappers'
          import mitt from 'mitt'
          
          export default boot(({ app }) => {
            app.use({
              install: function (Vue, options) {
                const pagebus = mitt()
                app.config.globalProperties.$$on = pagebus.on
                app.config.globalProperties.$$emit = pagebus.emit
              }
            })
          })
          

          If you wish to debug:

             ...
             app.config.globalProperties.$$on = function (ev, ...args) {
                console.log(ev, args)
                return pagebus.on(ev, ...args)
             }
             ...
          
          1 Reply Last reply Reply Quote 1
          • First post
            Last post