如何通过 Vuex 中的 Mutation 推送到数组?

How to push to an array via a Mutation in Vuex?

At the time I was writing this question I found the solution to my problem, but even so I decided to share it with the community to see if I'm solving the problem in the best way possible.

鉴于我的商店摘要:

//  store/index.js

const store = createStore({
  state: {
    userBooks: [],
  }
  mutations: {
    setUserBooks(state, val) {
      state.userBooks.push(val);
    },
  actions: {
    addBook({ commit }, payload) {
      commit("setUserBooks", payload);
  }
})

我这样调用操作:

//  Add.vue

methods: {
  addBook(book) {
    this.$store.dispatch("addBook", book);
  },
}

这给了我以下错误:

Uncaught (in promise) TypeError: state.userBooks.push is not a function

我已经检查过这个解决方案:。这正是我所尝试的,但我得到了上述错误。

我是如何解决问题的:

我注意到 book 对象作为代理对象进入函数。考虑到这一点,我将代理对象变成了一个常规对象,如下所示:

addBook(book) {
  book = Object.assign({}, book);
  this.$store.dispatch("addBook", book);
}

为什么会出现这个问题?

我承认我还是不明白为什么会出现这个问题。 book是通过booksv-for得到的。 books 由 Google 图书 API 查询组成。使用 axios.get().then()

完成查询

console.log(this.books) 已经 returns 我是一个代理对象,我承认我不知道这是否是预期的行为,我是否应该尝试改变它。

无论如何问题都解决了,但如果有人有任何不同的方法,我会很乐意学习新的东西。


编辑:更多代码

我决定编辑问题以展示 books 是如何生成和填充的。

<template>
    <figure v-for="(book, index) in books" :key="index">
      <Button text="+" @click="addBook(book)" />
      <!-- I omitted the use of the other elements to make things more objective. -->
    </figure>
</template>

<script>
export default {
  data() {
    return {
      books: {},
    };
  },
  methods: {
    search() {
      axios
        .get(`https://www.googleapis.com/books/v1/volumes?q=${this.seek}`)
        .then((response) => {
          this.books = response.data.items.map((item) => ({
            id: item.id,
            title: item.volumeInfo.title,
            authors: item.volumeInfo.authors || [this.$t("book.unknown-author")],
            ISBN: item.volumeInfo.industryIdentifiers?.[0].identifier ?? item.id,
            thumbnail: item.volumeInfo.imageLinks?.thumbnail ?? this.noCover,
          }));
        })
        .catch((error) => console.error(error))
    },
    addBook(book) {
      // Object.assign({}, book)
      book = { ...book };
      this.$store.dispatch("addBook", book);
    },
  },
};
</script>

另一种更快的新方法是展开运算符。您在 book 对象中创建一个新对象和 spred 变量。它的工作原理与 book = Object.assign({}, book)

相同
book = { ...book }

下面是 spred 运算符的更多用法示例:

  • 您可以在数组中使用它,如果 val 是一个带有对象的数组,如果不是,则不要在 val 之前键入 ...
setUserBooks(state, val) {
      state.userBooks = [...state.userBooks, ...val];
}
  • 或者例如,您有一个名为 user 的大对象,您在这个对象中有他的 address 对象,他想更改它。
setUser(state, address) {
      state.user = {...state.user, address};
}