下面是一个带有parameterized getter的Vuex存储的示例,我需要将其映射到Vue实例,以便在模板中使用.

const store = new Vuex.Store({
  state: {
    lower: 5,
    higher: 10,
    unrelated: 3
  },
  getters: {
    inRange: state => value => {
      console.log('inRange run')
      return (state.lower <= value) && (state.higher >= value)
    }
  },
  mutations: {
    reduceLower: state => state.lower--,
    incrementUnrelated: state => state.unrelated++
  }
})

new Vue({
  el: '#app',
  template: "<div>{{ inRange(4) }}, {{ unrelated }}</div>",
  store,
  computed: Object.assign(
    Vuex.mapGetters(['inRange']),
    Vuex.mapState(['unrelated'])
  ),
})

setTimeout(function() {
  console.log('reduceLower')
  store.commit('reduceLower')
  setTimeout(function() {
    console.log('incrementUnrelated')
    store.commit('incrementUnrelated')
  }, 3000);  
}, 3000);
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vuex/dist/vuex.js"></script>
<div id="app"></div>

首先,这似乎是有效的工作代码.然而,考虑到computed意味着一组缓存的计算(computed)属性,我很好奇这个场景中的行为,是否存在缓存?如果没有,有没有考虑到性能方面的问题?即使该函数不会导致任何状态更改,它是否应该是method

这是反模式吗?这个例子不是真实的,但我确实想在store 中集中逻辑.

UPDATE

我更新了这个示例,以说明对inRange getter所基于的基础lower/higher值的修改对于Vue实例来说确实是被动的(尽管没有映射为状态).我还包括了一个unrelated值,它不是计算的一部分,如果映射的getter被缓存,修改不相关的值不应该触发getter再次被调用,但是它确实会被调用.

我的结论是,没有缓存,因此它的性能比传统的计算(computed)属性差,但在功能上仍然正确.

这个模式是否存在任何缺陷,或者是否存在性能更好的缺陷,这个问题仍然悬而未决.

推荐答案

在我看来,这是一种反模式.这是一种奇怪的方法.此外,这里没有缓存,因为inRange会立即返回一个值(最终函数),而不使用state中的任何成员——因此Vue检测到0个被动依赖项.

getter不能以这种方式参数化,它们只能派生基于状态的东西.因此,如果该范围可以存储在state中,那么它将起作用(并将被缓存).

类似的问题:vuexjs getter with argument

既然你想集中这种行为,我认为你应该在一个单独的模块中完成,也许作为一个mixin.这也不会被缓存,所以您必须将其(和输入)包装到组件的computed中,或者使用其他一些备忘录

比如:

import { inRange } from './state/methods';
import { mapGetters }  from 'vuex';

const Example = Vue.extend({
  data: {
    rangeInput: 10
  },
  computed: {
    ...mapGetters(['lower', 'higher']),
    inRange() {
      return inRange(this.rangeInput, this.lower, this.higher);
    }
  }
});

Vue.js相关问答推荐

NUXT 3 在客户端获取数据

有什么理由不在 vue3 中使用