13

问题

Vue 2: 计算属性在 vuex 存储突变后更新。

Vue 3: 计算属性在 vuex 存储突变后不会更新。

Vuex 4

目的:从 Firestore 获取帖子。添加到“postsArray”。提交突变。

注意:函数“getNextPosts”是从允许无限滚动的(工作)交叉点观察者调用的。

const postsArray: Array<string> = [];
const vuexStore = createStore({
  state: {
    posts: []
  },
  actions: {
    // See https://firebase.google.com/docs/firestore/query-data/query-cursors#paginate_a_query
    getFirstPosts({ commit }) {
      const getFirstPosts = async () => {
        const firstPostsQuery = firestore.collection("posts").limit(3);

        // Get FIRST posts.
        const firstPosts = await firstPostsQuery.get();

        // Add to postsArray.
        for (const doc of firstPosts.docs) {
          postsArray.push(doc.id);
        }

        // Add to vuex store.
        commit("addFirstPostsToVuex", postsArray);

        // Set reference.
        lastPostDownloaded = firstPosts.docs[2]; // 3rd post.
      };
      getFirstPosts();
    },
    getNextPosts({ commit }) {
      const getNextPosts = async () => {
        const nextPostsQuery = firestore
          .collection("posts")
          .startAfter(lastPostDownloaded)
          .limit(2);

        // Get NEXT posts.
        const nextPosts = await nextPostsQuery.get();

        // Add to postsArray.
        for (const doc of nextPosts.docs) {
          postsArray.push(doc.id);
        }

        // Add to vuex store.
        commit("addNextPostsToVuex", postsArray);

        // Update reference.
        lastPostDownloaded = nextPosts.docs[1]; // 2nd post.
      };
      getNextPosts();
    }
  },
  mutations: {
    addFirstPostsToVuex(state, value) {
      state.posts = value;
    },
    addNextPostsToVuex(state, value) {
      state.posts = value;
    }
  }
});

计算属性

export default ({
  computed: {
    posts() {
      // List rendering.
      return vuexStore.state.posts;
    }
  }
});

v-for

<template>
  <div id="feed">
    <article class="post" v-for="post in posts" v-bind:key="post.id">
      <header class="info">
        {{ post }}
      </header>
    </article>
  </div>
</template>
4

4 回答 4

1

新旧版本在 Vuex 内部的状态定义略有不同。

**In Vuex3 state was just a prop with an Object while in Vuex4 it has return an Object or a function which returns an Object.**

从 V3 迁移到 V4 时,您一开始可能不会注意到差异,因为 V3 样式也适用于 V4。当您拥有模块并拥有它们的多个实例时,差异就会显示出来。然后状态必须是一个返回对象以避免状态污染的函数(如 tony19 所述)。

模块:

// Vuex 3.x Module
const moduleVUEX3 = {
    export const state = { ... }
}

// Vuex 4.x Module
const moduleVUEX4 = {
    export const state = () => ({ ... })
}

单店:

// Vuex 3.x
import Vuex from 'vuex'

const store = new Vuex.Store({
  state: { ... }
})


// Vuex 4.x
import { createStore } from 'vuex'

const store = createStore({
  state() {
    return { ... }
  }
})

这个问题的解决方案是:

const vuexStore = createStore({
  state: return {
    posts: []
  }
})
于 2021-10-21T10:26:44.557 回答
0

我通常这样使用它

<script setup lang="ts">
import { computed, reactive,ComputedRef } from "vue";
import { useStore } from "vuex";
interface State {
  shadow: ComputedRef<boolean>
}
const store = useStore();

const state = reactive<State>({
  shadow: computed(() => store.state.shadow),
)}
</script>

当vuex中的状态发生变化时,页面会及时响应,希望对你有帮助

于 2021-10-30T05:32:01.453 回答
-1

您可以尝试删除 postsArray,我认为它与反应性有关。

尝试将突变更改为

addFirstPostsToVuex(state, docId) {
      state.posts.push(docId);
    }

然后在你做的动作中

for (const doc of firstPosts.docs) {
          commit("addFirstPostsToVuex",doc.id);
        }
于 2021-10-27T19:35:20.297 回答
-2

如果您使用mapState函数将 store 的状态映射到 Vue 组件的状态,则可以解决此问题。

在上面的代码中,这将是这样的:

import { mapState } from "vuex";
import { defineComponent } from "vue";

export default defineComponent({
     computed: {
        ...mapState(["posts"])
     }
});

v-for 现在应该可以正常工作了。

参考:https ://vuex.vuejs.org/guide/state.html和https://scrimba.com/scrim/c8Pz7BSK?pl=pnyzgAP

于 2020-12-07T07:06:00.233 回答