3

I have two <router-view/>s: main and sidebar. Each of them is supplied with a component (EditorMain.vue and EditorSidebar.vue).

EditorMain has a method exportData(). I want to call this method from EditorSidebar on button click.

What is a good way of tackling it?

  • I do use vuex, but i don't wanna keep this data reactive since the method requires too much computational power.

  • I could use global events bus, but it doesn't feel right to use it together with vuex (right?)

  • I could handle it in root of my app by adding event listener to router-view <router-view @exportClick="handleExportData"> and then target editor component, but it does not feel right as well as later i could need 100 listeners.

Is there any good practice for this? Or did i make some mistakes with the way app is set up? Did is overlooked something in documentation?

2 Answers 2

1

After two more years of my adventure with Vue I feel confident enough to answer my own question. It boils down to communication between router views. I've presented two possible solutions, I'll address them separately:

Events bus

Use global events bus (but it doesn't feel right to use it together with vuex)

Well, it may not feel right and it is surely not a first thing you have to think about, but it is perfectly fine use-case for event-bus. The advantage of this solution would be that the components are coupled only by the event name.

Router-view event listeners

I could handle it in root of my app by adding event listener to router-view <router-view @exportClick="handleExportData"> and then target editor component, but it does not feel right as well as later i could need 100 listeners.

This way of solving this problem is also fine, buy it couples components together. Coupling happens in the component containing <router-view/> where all the listeners are set.

Big number of listeners could be addressed by passing an object with event: handler mapping pairs to v-on directive; like so:

<router-view v-on="listeners"/>

...

data () {
   return {
      listeners: {
         'event-one': () => console.log('Event one fired!'),
         'event-two': () => console.log('The second event works as well!')
      }
   }
Sign up to request clarification or add additional context in comments.

Comments

1

You could create a plugin for handling exports:

import Vue from 'vue'

ExportPlugin.install = function (Vue, options) {
  const _data = new Map()
  Object.defineProperty(Vue.prototype, '$exporter', {
      value: {
          setData: (svg) => {
              _data.set('svg', svg)
          },
          exportData: () => {
              const svg = _data.get('svg')
              // do data export...
          }
       }
  })
}

Vue.use(ExportPlugin)

Using like:

// EditorMain component
methods: {
    setData (data) {
        this.$exporter.setData(data)
    }
}

// EditorSidebar
<button @click="$exporter.exportData">Export</button>

6 Comments

sounds like an interesting approach, however i'm not sure how could i get private data from EditorMain inside of plugin's value: () => {} function.
Right. And how do i trigger writing the data then?
Is the data coming from an API? If so you could do something like this.$store.commit('export/data') in the success callback.
no, it is not coming from API. It is processed SVG. Processing of this SVG costs a lot of computational power and it contens change quite often - sometimes every tick. That's why it can't be saved in a state.
I had another thought, see if my updated answer looks like a better approach.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.