【问题标题】:Vue.js Object in array undefined in data from store来自商店的数据中未定义的数组中的 Vue.js 对象
【发布时间】:2020-07-15 13:56:05
【问题描述】:

很抱歉,如果这真的很明显,但我是 Vue 新手,需要一些帮助。

我正在从我的存储中获取一组数据(帖子)并尝试控制台记录数组中的一个对象,但它每次都显示未定义。如果我控制台记录整个数组,它会返回正常。

我猜这与 created 钩子中的 console.log 之前没有加载数据有关?我已经尽我所能尝试了,这让我发疯了。任何帮助表示赞赏(下面的简化代码)。

<script>
        export default {
          components: {},

     computed: {
            posts() {
              return this.$store.state.posts;
            }
          },
          created() {
            this.$store.dispatch("getPosts");
           console.log(this.posts[0])
           },
        };
        </script>


//Store code Below

export const state = () => ({
      posts: [],
    })

    export const mutations = {
      updatePosts: (state, posts) => {
        state.posts = posts
      }
    }

    export const actions = {
      async getPosts({
        state,
        commit,
        dispatch
      }) {
        if (state.posts.length) return

        try {
          let posts = await fetch(
            `${siteURL}/wp-json/wp/v2/video`
          ).then(res => res.json())

          posts = posts
            .filter(el => el.status === "publish")
            .map(({
              acf,
              id,
              slug,
              video_embed,
              title,
              date,
              content
            }) => ({
              acf,
              id,
              slug,
              video_embed,
              title,
              date,
              content
            }))

          commit("updatePosts", posts)
        } catch (err) {
          console.log(err)
        }
      }
    }

【问题讨论】:

    标签: arrays vue.js object vuex nuxt.js


    【解决方案1】:

    控制台行为说明

    当您将对象或数组记录到控制台,然后单击以展开/查看属性时,控制台会在单击时向您显示属性现在,而不是日志的时间。因此,如果它们在记录后发生变化,您将看到新值。

    怎么样?由于对象和数组是引用变量,因此控制台会存储引用,然后在您单击时自行更新。这仅适用于对象和数组。

    相反,当您将原语记录到控制台时,您只能看到它在记录时的样子。

    在 Chrome 中,您还会在控制台中的对象旁边看到一个蓝色小方块。当您将鼠标悬停时,它会告诉您,“下面的值刚刚被评估。”


    这就是为什么您在记录一个项目时从未看到该值的原因,因为它是一个尚不存在的项目。但是posts 总是有一个引用,因为它被初始化为一个空数组。因此,在记录 posts 引用时,当您单击时,数据已经到达。

    这里有一个demo 试图说明这一点。

    【讨论】:

    • 不客气。另外,请注意尝试通过 Vuex 操作承诺(await 或 .then)访问 created 中新加载的数据的反模式。这是not considered a good practice。
    【解决方案2】:

    如果要在 created() 钩子上获取正确的数据,则应在显示数据之前执行该操作。

    1. 在created() 钩子中,您可以异步调度操作。
    async created() {
        await this.$store.dispatch("getPosts");
        console.log(this.posts[0])
    },
    
    1. 您可以使用 JavaScript Promises。
    async created() {
        this.$store.dispatch("getPosts").then(()=> {
            console.log(this.posts[0]);
        });
    },
    

    【讨论】:

      【解决方案3】:

      您需要按照文档https://vuex.vuejs.org/guide/actions.html#composing-actions 使用承诺。您的操作没有返回其获取数据的承诺,也没有在 console.logged 结果之前等待承诺解决。 Promise 是一个需要掌握的非常重要的概念。这是一个与您的代码基本匹配的示例,尽管我使用 setTimeout 而不是真正的 fetch 调用。

      const store = new Vuex.Store({
        state: {
          posts: []
        },
        getters: {
          itemList: (state) => {
            return state.items;
          }
        },
        mutations: {
          updatePosts: (state, posts) => {
            state.posts = posts
          }
        },
        actions: (actions = {
          async getPosts({ state, commit, dispatch }) {
            if (state.posts.length) {
              return Promise.resolve();
            }
      
            try {
              return new Promise(resolve => setTimeout(() => {
                const posts = [{ id: 42 }];
                commit("updatePosts", posts);
                resolve();
              }, 1000));
              
            } catch (err) {
              console.log(err);
            }
          }
        })
      });
      
      const app = new Vue({
        el: "#app",
      
        computed: {
          posts() {
            return this.$store.state.posts;
          }
        },
        created() {
          this.$store.dispatch("getPosts").then(() => console.log(this.posts[0]));
        },
        store
      });
      <script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
      <script src="https://unpkg.com/vuex@2.5.0/dist/vuex.js"></script>
      <div id="app">
      </div>

      【讨论】:

        【解决方案4】:

        你得到一个 undefined 因为异步函数还没有填充状态。 对于异步数据,您应该始终使用 getter。

        getter 的结果是根据它的依赖来缓存的,只有当它的一些依赖发生变化时才会重新评估。

        Vuex Getters

        // Store
        export const getters = {
            get_posts(state) {
                return state.posts;
            }
        }
        

        -

        // component
        computed: {
            posts() {
                return this.$store.getters['get_posts'];
            }
        };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-03-23
          • 1970-01-01
          • 2021-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-01-14
          • 2021-12-23
          相关资源
          最近更新 更多