【问题标题】:Vue3//Vuex - how do I add the store only after it has initialized its modules?Vue3//Vuex - 如何仅在初始化其模块后添加商店?
【发布时间】:2021-01-22 19:38:44
【问题描述】:

我之前遇到了一个问题,mapState() 不会为存储模块自动创建(简单的值检索)getter。或者也许这是一个时间问题。文档是这样说的:

"当一个组件需要使用多个存储状态属性时 或 getter,声明所有这些计算属性可能会重复 并且冗长。为了解决这个问题,我们可以使用 ma​​pState 助手 为我们生成计算的 getter 函数,为我们节省了一些 击键:"

https://vuex.vuejs.org/guide/state.html

在组件计算属性中使用 mapState() 效果很好 - 直到我将该状态的一部分移到模块中,此时它停止工作。添加一个 getter 来拉取 state 属性确实有效,但我不喜欢在检索简单而不是计算的值时重复代码。如果是因为时间问题,是不是某个地方有 store.ready(app.use(store)) 函数?

// store.js
import { createStore } from 'vuex';
import products from './products.js'
import cart from './cart.js'

const store = createStore({
   modules:{
      products,
      cart
   },
   state() {
      return {
         isLoggedIn: false,
      }
   },
   mutations: {
      login(state) {
         state.isLoggedIn = true;
      },
      logout(state) {
         state.isLoggedIn = false;
      },
   },
})

export default store;
// products.js

export default {
   state() {
      return {
         products: [
            {
               id: 'p1',
               image:
                  'https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Books_HD_%288314929977%29.jpg/640px-Books_HD_%288314929977%29.jpg',
               title: 'Book Collection',
               description:
                  'A collection of must-read books. All-time classics included!',
               price: 99.99,
            },
         ],
      }
   },
   getters:{
      products(state){
         return state.products;
      }
   }
}
<!-- productList.vue -->

<template>
  <section>
    <ul>
      <product-item
        v-for="prod in products"
        :key="prod.id"
        :id="prod.id"
        :title="prod.title"
        :image="prod.image"
        :description="prod.description"
        :price="prod.price"
      ></product-item>
    </ul>
  </section>
</template>

<script>
import ProductItem from '../components/products/ProductItem.vue';
import { mapState } from 'vuex'
//import { mapGetters } from 'vuex'

export default {
  components: {
    ProductItem,
  },
  computed: {
    ...mapState([       //This does not work
      'products'
    ])
    // ...mapGetters([    This does
    //   'products'
    // ])
  },
  mounted(){
    console.log(this.products)
  }
};
</script>

<style scoped>
  ul {
    list-style: none;
    margin: 2rem auto;
    padding: 0;
    max-width: 40rem;
  }
</style>

【问题讨论】:

  • 您可以将mapState 与模块一起使用。请更新问题以显示将其与模块一起使用的代码。
  • 我添加了一些代码。我应该提到我在控制台中看到了 this.products,所以它就在那里。但是当我使用 mapState 时,v-for 并没有选择它。当我切换到 mapGetters 时,它确实会捡起它。在我切换到模块之前它就可以工作了。
  • 你的模块有命名空间吗?他们不在你的问题中,但这不是很典型

标签: vue.js vuex vuejs3 vuex-modules


【解决方案1】:

模块状态是 always 命名空间的。例如,您在products 模块中的products 状态仅在

//         ? module ? state
store.state.products.products

要将mapState 与模块一起使用,您可以使用以下任一选项

computed: {
  ...mapState({
    products: state => state.products.products
  }),
  ...mapState("products", {
    products: state.products
  })
  ...mapState("products", [
    "products"
  ])
}

其中的每一个都会将products 状态从products 模块映射到组件中的this.products


您的 getter 可以工作,因为您的模块没有命名空间,因此...

默认情况下,模块内的动作、突变和getter仍然注册在全局命名空间

https://vuex.vuejs.org/guide/modules.html#namespacing

【讨论】:

  • 谢谢。鉴于此解释和上面的代码,为什么我在使用 mapState() (mounted()) 时会在控制台中看到产品结构?这就是让我感到震惊的原因 - this.products 在那里,但 v-for 无法识别它。
  • @Daemach 抱歉,我没在那儿跟着你。如果您需要澄清一些事情,请edit your question 这样您就可以添加一些适当的代码示例
  • 在上面的代码示例中,我使用 mapState() 并执行 .mounted() { console.log(this.products) }。在控制台可以看到产品数组,为什么v-for看不到呢?
  • @Daemach 您在控制台中究竟看到了什么?因为您的模块也称为products,所以它可能将store.state.products(模块)映射到this.products。如果您看到一个带有“products”键的对象,例如{"products": [...]},那么就是这种情况
  • 是的,这就是我所看到的。再次感谢您的帮助和解释。
猜你喜欢
  • 2018-07-17
  • 2018-10-24
  • 2018-05-19
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
  • 2019-12-06
  • 1970-01-01
  • 2019-11-04
相关资源
最近更新 更多