来自商店的数据中未定义的数组中的 Vue.js 对象

Posted

技术标签:

【中文标题】来自商店的数据中未定义的数组中的 Vue.js 对象【英文标题】:Vue.js Object in array undefined in data from store 【发布时间】: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)
        
      
    

【问题讨论】:

【参考方案1】:

控制台行为说明

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

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

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

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


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

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

【讨论】:

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

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

    created() 钩子中,您可以异步调度操作。
async created() 
    await this.$store.dispatch("getPosts");
    console.log(this.posts[0])
,
    您可以使用 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'];
    
;

【讨论】:

以上是关于来自商店的数据中未定义的数组中的 Vue.js 对象的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js this 在计算属性中未定义

laravel中的vue js..计算方法未定义

如何使用 Vue.js 为数组(数据)中的所有对象添加属性?

Nuxt vuex状态菜单列表:组件中未定义

无法读取数组中未定义的“数据”

Vue.js- Vuex 更新数组中的对象,内部状态未反映在组件 DOM 中