VueJS:在组件之间使用全局对象的最佳实践?

时间:2019-02-15 01:46:45

标签: javascript vue.js vuex

User.js类和用户对象(user = new User();)。

user对象正在所有嵌套组件中使用。在User类中,有很多重要的方法。

如何简单地在任何组件中使用/访问this.userthis.$user及其方法?

1-解决方案 (临时工作解决方案):在vuex的商店中设置user,并在所有组件的{{ 1}}:

data

缺点:应在每个组件中添加。注意:组件太多。

2-解决方案 :将用户添加到Vue的原型中,例如插件:

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

缺点:Vue.prototype.$user = user 的数据更改时,在DOM元素(UI)中不会影响

3-解决方案 :放入组件的道具

缺点:应在每个组件中添加。注意:同样,组件太多。

我发现的所有解决方案都存在问题,尤其是随着项目的规模越来越大。

任何建议和解决方案将不胜感激!

6 个答案:

答案 0 :(得分:4)

基于@Denis的答案,特别是建议3 ,这是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;

main.js

import UserPlugin from './common/UserPlugin';

Vue.use(UserPlugin);

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

为了进一步使用,我发布了一个小型图书馆来解决这些问题:

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

答案 1 :(得分:3)

建议1:使用vuex中的吸气剂

  • 您可以将Vuex中的gettersmapGetters结合使用,以将用户包括在每个组件的计算属性中。

Vuex

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

组件

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

建议2:通过插件添加观察者

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;

建议3:通过mixin添加计算属性user作为插件

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;

答案 2 :(得分:1)

您可以使用mixins将User.js添加到您的根组件中,例如

import userLib from './User';
//User.js path should correct

然后

var app = new Vue({
    router,
    mixins: [
        userLib
    ],
  //.....
});

之后,您可以在任何组件中使用这些User方法中的任何一个

this.$parent.userClassMehtod();

或是否有数据访问

this.$parent.userClassData;

最后不要忘记在export default{//..}中添加User.js

注意:仅当您将User.js的所有方法导出到export default

中时,此方法才有效

答案 3 :(得分:1)

假设您实际上并没有在每个组件中使用user的所有方法/属性,而是每次都使用它们的子集,我看不出解决方案1和2对您不起作用的任何原因,因为不必将整个user对象传递给每个组件。

比方说,您的对象User具有一些属性(a1,a2,a3等)和方法(m1,m2,m3 ...)。如果某个组件仅需要其中的一部分(例如a1,a2,m1,m2,m3),则使用Vuex,您可以使用映射函数(mapState,mapGetters,mapMutations和mapActions)从user <获取确切的信息/ p>

import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
export default {
    computed: {
        ...mapState('user', [ 'a1' ]),
        ...mapGetters('user', [ 'a2' ])
    },
    methods: {
        ...mapMutations('user', [ 'm1' ]),
        ...mapActions('user', [ 'm2', 'm3' ])
    }
}

对于解决方案2(使用原型),要在user数据更改时进行组件更新,可以通过methods将必要的数据映射到组件。

export default {
    methods: {
        userA1() {
            return this.$user.attributes.a1;
        },
        userM1() {
            this.$user.methods.m1();
        }
        // and so on
    }
}

更好的是,您可以创建mixin来显式映射user中的数据,并重用mixins以避免组件中的重复代码。它可以同时应用于Vuex解决方案和原型解决方案。

// mixin1:
const mixin1 = {
    computed: {
        ...mapState('user', [ 'a1' ]),
    },
    methods: {
        ...mapMutations('user', [ 'm1' ])
    }
}

// mixin2:
const mixin2 = {
    computed: {
        ...mapGetters('user', [ 'a2' ]),
    },
    methods: {
        ...mapActions('user', [ 'm2', 'm3' ])
    }
}

// component1
export default {
    mixins: [ mixin1 ]
}

// component 2
export default {
    mixins: [ mixin1, mixin2 ]
}

但是,如果您确实需要将整个对象user传递给每个组件,则无能为力。相反,您应该查看实现,并查看是否有更好的方法可以将对象分解为更小的有意义的对象。

答案 4 :(得分:1)

我刚刚创建了最小的codesandbox,以清除关于dependency Injection如何工作的想法。

答案 5 :(得分:-3)

您可以拥有第二个Vue实例并声明一个反应性属性。

See: Reactivity in depth