ChatGPT解决这个技术问题 Extra ChatGPT

在 Vuex 突变中访问 getter

在 Vuex 存储突变中,是否可以访问 getter?考虑下面的例子。

new Vuex.Store({
    state: {
        question: 'Is it possible to access getters within a Vuex mutation?'
    },
    mutations: {
        askQuestion(state) {
            // TODO: Get question from getter here
            let question = '';

            if (question) {
                // ...
            }
        }
    },
    getters: {
        getQuestion: (state) => {
            return state.question;
        }
    }
});

当然,这个例子没有多大意义,因为我可以直接访问突变中 state 对象的 question 属性,但我希望你能看到我想要做什么。也就是说,有条件地操纵状态。

在突变中,thisundefinedstate 参数允许访问 state 对象,而不是存储的其余部分。

The documentation on mutations 没有提到任何关于这样做的内容。

我的猜测是这是不可能的,除非我错过了什么?我想另一种选择是在商店之外执行此逻辑(导致代码重复)或实施执行此操作的操作,因为操作可以访问整个商店上下文。我很确定这是一种更好的方法,那就是让突变专注于它实际应该做的事情;改变状态。这可能是我最终会做的事情,但我只是好奇是否可以访问突变中的吸气剂?

您能否详细说明为什么在突变中需要吸气剂?您是对的,您的示例可以轻松引用 state.question。而且,是的,任何会根据当前状态采取不同 action 的逻辑都应该在一个动作中处理。
您可以在操作中访问 getter,因为操作将上下文作为第一个参数。像这样:actions: { action1: (context, payload) => { console.log(context.getters.getSomething); }}。不过,不确定您是否可以在突变中做到这一点,因为突变仅接收本地“状态”。
@thanksd 因为我的真实代码比这更复杂,我需要检查一些东西。具体示例是将产品添加到购物车,我想检查它是否已经存在。我想将这种逻辑排除在突变之外以保持其清洁。我很确定最好的方法也是使用一个动作,但只是好奇是否有可能在突变中访问吸气剂——无论出于何种原因。
此功能已被 Vuex 团队请求但被拒绝,请参阅 this issue 了解整个讨论、解释和一些解决方法

t
thanksd

Vuex 存储变异方法不提供对 getter 的直接访问。

这可能是不好的做法*,但您可以在提交突变时传递对 getters 的引用,如下所示:

actions: {
  fooAction({commit, getters}, data) {
    commit('FOO_MUTATION', {data, getters})
  }
},
mutations: {
  FOO_MUTATION(state, {data, getters}) {
    console.log(getters);
  }
}

* 最好的做法是让突变尽可能简单,只直接影响 Vuex 状态。这使得推理状态变化变得更容易,而无需考虑任何副作用。现在,如果您遵循 vuex getter 的最佳实践,它们首先不应该有任何副作用。但是,任何需要引用 getter 的逻辑都可以在操作中运行,该操作具有对 getter 和状态的读取访问权限。然后该逻辑的输出可以传递给突变。因此,您可以将对 getters 对象的引用传递给突变,但没有必要这样做,这会使水变得混乱。


谢谢!我会采取行动,因为这似乎更合适。我同意传递 getter 是一种解决方法,但我仍然没有想到这一点。感谢您的澄清! :-)
什么是坏习惯?在突变或特定解决方案中使用吸气剂?
谢谢@thanksd,所以简而言之,在行动中做肮脏的工作,而不是在突变中?
这些规则很荒谬
K
Kees de Kooter

如果您将 getter 和 mutation 放在单独的模块中,则可以在 mutation 中导入 getter,然后执行以下操作:

import getters from './getters'

askQuestion(state) {
  const question = getters.getQuestion(state)
  // etc
}

虽然如果你的吸气剂看起来像这样呢? export const mygetter = (state, getters) => (id) => { return state.blah }
import mygetter from './getters'; askQuestion(state) { const question = mygetter(state)
d
dyslexit

如果有人正在寻找一个简单的解决方案,@bbugh 写出了一种解决此问题的方法 here,只需让突变和 getter 都使用相同的函数:

function is_product_in_cart (state, product) {
  return state.cart.products.indexOf(product) > -1
}

export default {
  mutations: {
    add_product_to_cart: function (state, product) {
      if (is_product_in_cart(state, product)) {
        return
      }
      state.cart.products.push(product)
    }
  },

  getters: {
    is_product_in_cart: (state) => (product) => is_product_in_cart(state, product)
  }
}

g
geoidesic

另一种解决方案是导入现有商店。假设您正在使用模块并且您的模块名为 foo,您的 mutator 文件将如下所示 store/foo/mutations.js

import index from '../index'
export const askQuestion = (state, obj) => {
    let store = index()
    let getQuestion = store.getters['foo/getQuestion']
}

我并不是说这是最佳做法,但它似乎有效。


L
Lautaro Ramos

如果将 store 声明为表达式,您还可以在突变中引用 Store 对象,如下所示:

const Store = new Vuex.Store({
  state: {...},
  getters: {...},
  mutations: {
    myMutation(state, payload) {
      //use the getter
      Store.getters.getter
    }
  }
});


{...} 中有什么?在我看来,您正在创建一家新商店,而不是引用现有商店。
这只是“状态在这里”的简写 - 我认为海报的意思是你在创建原始商店时这样做,然后你可以通过你分配给它的任何 const 来引用它,在这种情况下,“商店”
A
Alexandr

用 vuex 4 测试

const state = () => ({
  some_state: 1
})

const getters = {
  some_getter: state => state.some_state + 1
}

const mutations = {
  GET_GETTER(state){
    return getters.some_getter(state)
  }
}

在你组件的某个地方

store.commit('GET_GETTER') // output: 2

如果您的 getter 本身使用另一个 getter,这将不起作用,例如:(state, getters) => getters.counter + 1