Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJS: Best practice for working with global object between components?

there is User.js class and user object(user = new User();).

The user object is being used in all nested components. in User class there are so many important methods.

How can I simply use/access this.user or this.$user and its methods in any component?

1-solution (temporary working solution): Setting user in vuex's store and define in all components' data:

data(){
  return {
    user:this.$store.state.user
  }
}

Cons: in every component, this should be added. Note: there are so many components.

2-solution: adding user to Vue's prototype like plugin:

Vue.prototype.$user = user

Cons: when user's data changes, it doesn't effect in DOM element (UI).

3-solution: putting to components's props.

Cons: in every component, this should be added. Note: Again there are so many components.

All of the solutions I found have issues, especially as the project gets larger and larger.

Any suggestion and solution will be appreciated!

like image 651
mudin Avatar asked Feb 15 '19 01:02

mudin


2 Answers

Note: Applies for Vue 2x

Proposal 1: Using getters from vuex

  • You could use getters along with mapGetters from Vuex to include users within computed properties for each component.

Vuex

getters: {
  // ...
  getUser: (state, getters) => {
    return getters.user
  }
}

component

import { mapGetters } from 'vuex'
computed: {
  ...mapGetters([getUser])
}

Proposal 2: add a watcher via plugin

Vue

// When using CommonJS via Browserify or Webpack
const Vue = require('vue')
const UserPlug = require('./user-watcher-plugin')

// Don't forget to call this
Vue.use(UserPlug)

user-watcher-plugin.js

const UserPlug = {
  install(Vue, options) {
    // We call Vue.mixin() here to inject functionality into all components.

    Vue.watch: 'user'
  }
};

export default UserPlug;

Proposal 3: add a computed property user as plugin via mixin

Vue

// When using CommonJS via Browserify or Webpack
const Vue = require('vue')
const UserPlug = require('./user-watcher-plugin')

// Don't forget to call this
Vue.use(UserPlug)

user-watcher-plugin.js

const UserPlug = {
  install(Vue, options) {
    // We call Vue.mixin() here to inject functionality into all components.

    Vue.mixin({
      computed: {
        user: function() {
          return this.$store.state.user
        }
      }
    })
  }
};

export default UserPlug;
like image 55
Denis Tsoi Avatar answered Nov 15 '22 14:11

Denis Tsoi


Based on @Denis answer, specifically Proposal 3, Here is the UserPlugin.js:

import store from '@/store/store';
import User from './User';

const UserPlugin = {
  install(Vue) {
    const $user = new User();
    window.$user = $user;
    store.commit('setUser', $user);
    Vue.mixin({
      computed: {
        $user() {
          return store.state.user;
        }
      }
    });
  }
};
export default UserPlugin;

and main.js:

import UserPlugin from './common/UserPlugin';

Vue.use(UserPlugin);

new Vue({
  render: h => h(App)
}).$mount('#app');

For further usage, I published small library for solving these kinda issues:

https://www.npmjs.com/package/vue-global-var

like image 22
mudin Avatar answered Nov 15 '22 14:11

mudin