Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access a Vue plugin from another plugins (using Vue.prototype)?

I'm trying to write a Vue plugin that's a simple abstraction to manage auth state across my app. This will need to access other Vue plugins, namely vuex, vue-router and vue-apollo (at the moment).

I tried extending Vue.prototype but when I try to access the plugin's properties how I would normally - eg. this.$apollo - I get the scope of the object, and therefore an undefined error. I also tried adding vm = this and using vm.$apollo, but this only moves the scope out further, but not to the Vue object - I guess this is because there is no instance of the Vue object yet?

export const VueAuth = {
  install (Vue, _opts) {
    Vue.prototype.$auth = {
      test () {
        console.log(this.$apollo)
      }
    }
  }
}

(The other plugins are imported and added via. Vue.use() in the main app.js)

Alternatively, I tried...

// ...
  install (Vue, { router, store, apollo })
// ...

but as a novice with js, I'm not sure how this works in terms of passing a copy of the passed objects, or if it will mutate the originals/pass by ref. And it's also very explicit and means more overhead if my plugin is to reach out to more plugins further down the line.

Can anyone advise on a clean, manageable way to do this? Do I have to instead alter an instance of Vue instead of the prototype?

like image 459
James Booth Avatar asked Apr 26 '19 20:04

James Booth


2 Answers

In the plugin install function, you do not have access to the Vue instance (this), but you can access other plugins via the prototype. For example:

main.js:

Vue.use(Apollo)
Vue.use(VueAuth) // must be installed after vue-apollo

plugin.js:

export const VueAuth = {
  install (Vue) {
    Vue.prototype.$auth = {
      test () {
        console.log(Vue.prototype.$apollo)
      }
    }
  }
}
like image 186
Chad von Nau Avatar answered Sep 25 '22 01:09

Chad von Nau


I found a simple solution for this issue:

In plugin installer you need to add value to not just prototype, but Vue itself to be able to use it globally.

There is a code example:

Installer:

import apiService from "../services/ApiService";
// Service contains 'post' method

export default {
  install(Vue) {
    Vue.prototype.$api = apiService;
    Vue.api = apiService;
  }
};

Usage in other plugin:

import Vue from "vue";

...

const response = await Vue.api.post({
  url: "/login",
  payload: { email, password }
});

Usage in component:

const response = await this.$api.post({
  url: "/login",
  payload: { email, password }
});

I'm not sure if that's a good solution, but that made my scenario work perfectly.

like image 32
Marius Jaskunas LeMarkiz Avatar answered Sep 27 '22 01:09

Marius Jaskunas LeMarkiz