渲染函数出错:“TypeError:无法读取未定义的属性”,使用Vuex和Vue Router

时间:2017-07-08 02:55:52

标签: javascript vuejs2 vue-router vuex

我一直在使用Vue,Vuex和Vue-Router处理问题。我正在构建一个闪存卡应用程序,在创建主应用程序时获取所有卡,然后使用Vuex getter获取每个卡的ID,该ID作为路由参数传递。

相关位:

App.vue

export default {
  components: {
    'app-header': header,
  },
  data() {
    return {
    }
  },
  created() {
    this.$store.dispatch('getAllCards');
  }
}

dispatch('getAllCards')只是从数据库中提取所有卡片并提交给Vuex store.js

现在我设置了getter

getters: {
  cardById: (state) => (id) => {
    return state.allCards.find((card) => card._id === id);
  }
}

以下是Card.vue

<template>
  <div>
    <br>
    <div v-if="flipped" class="container">
      <div class="box">
        <pre v-if="card.code"><code class="preserve-ws">{{card.back}}</code></pre>
        <p class="preserve-ws center-vertical" v-else>{{card.back}}</p>
      </div>
    </div>
    <div v-else class="container">
      <div class="box">
        <h1 class="title has-text-centered center-vertical is-2">{{card.front}}</h1>
      </div>
    </div>
</template>

<script>

export default {
  data() {
    return {
      card: {},
      flipped: false,
      general_card: false,
      code_card: true,
      random_card: false
    }
  },
  computed: {
  },
  methods: {
  },
  created() {
    this.card = this.$store.getters.cardById(this.$route.params.id);
  }
}
</script>

我收到了标题中引用的TypeError。我的理解是created()挂钩在data()设置完成后发生,因此我可以使用getter指定{card}。不幸的是,这没有显示......

如果我将card()指定为计算属性:

computed: {  
  card() {
    return this.$store.getters.cardById(this.$route.params.id);
  }
}

该卡显示,但我仍然在控制台中收到该错误。知道为什么吗?我看了this并尝试了解决方案,但无济于事。

5 个答案:

答案 0 :(得分:1)

您需要的是基于商店状态的派生状态,即根据卡ID返回已过滤的卡片。此ID通过路径参数接收到您的组件。因此,最好使用计算属性而不是将参数传递给商店getter

而不是在数据属性中初始化card使card计算属性如下:

computed:{
    card(){
        return this.$store.state.allCards.find((card) => card._id === this.$route.params.id);
    }
}

请注意

如果组件需要基于其自身状态派生的存储状态(在您的情况下为rourte参数),则应定义本地计算属性

答案 1 :(得分:1)

我尝试了其他所有人的解决方案但他们没有工作。但我终于让它上班了。这对我有用:

我最终加入了一个顶级:

<div v-if="!card"> Loading card... </div>
<div v-else> Rest of card template </div>

这似乎已经使错误沉默了。此外,该卡作为计算属性存在:

card() {
  return this.$store.getters.cardById(this.$route.params.id);
}

答案 2 :(得分:1)

问题没有得到正确答案的所有前提。 (我们不知道突变,状态,行动和我们没有关于app-header组件的线索) 所以我们必须承认一些假设:

    挂载组件时,
  1. state.allCards为空Array
  2. action getAllCards是一个异步函数,用于检索或设置带有变异的state.allCards
  3. cardById的getter,返回一个函数,因此vuex不能对函数应用反应。因此,如果状态发生变化,则不会正确触发吸气剂。 要解决此问题,请在提及here时使用computed

    但它没有修复undefined error,从我的观点来看,这是因为getters在mount上返回undefined

    getters: {
      cardById: (state) => (id) => {
        var card = state.allCards.find((card) => card._id === id);
        if(card) {
          return card;
        }
        // on undefined return a default value
        return {
          front:'default value'
        };
      }
    }
    

    您可以在此jsfiddle上看到实施,而控制台上没有错误。

    或者您可以在卡组件的未定义值上加载状态。

    如果我的假设错了,请提供一个帮助你的小伙伴。

答案 3 :(得分:0)

我认为这一步是抛出错误

getters: {
  cardById: (state) => (id) => {
    return state.allCards.find((card) => card._id === id);
  }
}

在此步骤中,它找不到汽车的_id,因为所有卡都是null;

然后你使用计算机代替,当所有牌都改变时,它会再次出现; 你可以改变这样的代码

getters: {
  cardById: (state) => (id) => {
    return state.allCards.find((card) => card && card._id === id);
  }
}

答案 4 :(得分:0)

$route.params.id必须是string,那么card._id的类型是什么?我认为每个card._id似乎都是number