使计算属性可供所有组件使用

moh*_*sen 6 javascript vue.js vuex

有没有办法使计算属性在全球范围内可用?

例如:假设 Vuex 存储中有一个“isAdmin”属性,我们可以使用 getter 来访问它。并且这个属性在很多组件中都被用来进行条件渲染。如何使其可供所有组件使用,而不是在每个组件计算属性中声明它?

ski*_*tle 5

已经有人建议您可以使用全局 mixin 来做到这一点。这会起作用,但不是唯一的方法。

虽然它不太可能对性能产生重大影响,但为此使用计算属性似乎有点浪费。每个组件都有自己的计算属性,并且每个组件都会保留该值的缓存副本。但这些值都是相同的。

此外,存储 getter 已经在该阶段缓存了值,因此在计算属性级别进行缓存并不能真正为我们节省任何东西。

相反,我们可以向 Vue 原型添加一个 JavaScript 属性 getter,通过代理来存储属性。从技术上讲,它不是一个计算属性,但其工作原理大致相同:

// These 5 lines are the important bit, the rest is just for demonstration purposes
Object.defineProperty(Vue.prototype, '$isAdmin', {
  get () {
    return this.$store.getters.isAdmin
  }
})

const store = new Vuex.Store({
  state: {
    isAdmin: false
  },
  
  mutations: {
    toggle (state) {
      state.isAdmin = !state.isAdmin
    }
  },
  
  getters: {
    isAdmin (state) {
      return state.isAdmin
    }
  }
})

new Vue({
  el: '#app',
  store,
  
  methods: {
    onClick () {
      this.$store.commit('toggle')
    }
  },
  
  watch: {
    $isAdmin () {
      console.log('$isAdmin watcher triggered')
    }
  }
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.1.1/dist/vuex.js"></script>

<div id="app">
  <p>{{ $isAdmin }}</p>
  <button @click="onClick">Change</button>
</div>
Run Code Online (Sandbox Code Playgroud)

有一个潜在的主要障碍。由于 Vuex 在内部使用 Vue 实例,isAdmin原型上定义的属性将与 Vuex 在幕后用于isAdmingetter 的自动生成的计算属性发生冲突。在上面的示例中,我通过调用组件属性来避免这个问题$isAdmin。理论上,这个问题也可以通过在创建商店后定义原型属性来避免。