来自对象键和嵌套数组的 Vue.js v-for 循环

Posted

技术标签:

【中文标题】来自对象键和嵌套数组的 Vue.js v-for 循环【英文标题】:Vue.js v-for loop from an object key and nested array 【发布时间】:2017-06-09 18:55:21 【问题描述】:

我在另一个 v-for 中安静了一个复杂的 v-for 循环。基本上显示问题列表和该问题的答案列表。我计划获取问题的密钥并将其用作 grouped_answers 的密钥。

v-for循环如下:

        <div v-for="question in questions.questions">
          question.question
          <div v-for="a in grouped_answers[0].answers">
            a.answer
          </div>
        </div>

当前返回错误:

无法读取未定义的属性“答案”。

grouped_answers 对象示例在这里:

[
  
    "question_id": 1,
    "answers": [
      
        "id": 1,
        "answer": "Cat"
      ,
      
        "id": 2,
        "answer": "Dog"
      
    ]
  ,
  
    "question_id": 2,
    "answers": [
      
        "id": 3,
        "answer": "Fish"
      ,
      
        "id": 4,
        "answer": "Ant"
      
    ]
  
]

对于完整的模板,我附上了下面的代码:

<template>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
              <div v-for="app in appliances">
                <input type="radio" id="one" v-model="appliance"  v-bind:value="app.id" v-on:change="getQuestions">
                <label for="one">app.appliance</label>
              </div>
              <br>
              <span>Picked: appliance</span>
              </br>
              </br>
                <div v-for="co in brands">
                  <input type="radio" id="two" v-model="brand"  v-bind:value="co.id">
                  <label for="one">co.brand</label>
                </div>
              <span>Picked:  brand </span>
              </br>
              </br>
                <input type="radio" id="one" value=1 v-model="age">
                <label for="one">1 Year</label>
                <br>
                <input type="radio" id="two" value=2 v-model="age">
                <label for="two">2 Years</label>
                <br>
                <input type="radio" id="two" value=3 v-model="age">
                <label for="two">3 Years</label>
                <br>
                <input type="radio" id="two" value=4 v-model="age">
                <label for="two">4 Years</label>
                <br>
                <input type="radio" id="two" value=5 v-model="age">
                <label for="two">5 Years</label>
                <br>
                <input type="radio" id="two" value=6 v-model="age">
                <label for="two">6 Years</label>
                <br>
                <input type="radio" id="two" value=7+ v-model="age">
                <label for="two">7+ Years</label>
                <br>
              <span>Picked:  age </span>
              <br>
              <br>
                <div v-for="question in questions.questions">
                  question.question
                  <div v-for="a in grouped_answers[0].answers">
                    answers.answer
                  </div>
                </div>
              <br>
              <br>
              grouped_answers[0]
              <br>
              <br>
                <input v-model="first_name" placeholder="First Name">
                <p>First Name is:  first_name </p>
                <input v-model="last_name" placeholder="Last Name">
                <p>Last Name is:  last_name </p>
                <input v-model="phone_number" placeholder="Phone Number">
                <p>Phone Number is:  phone_number </p>
                <input v-model="email" placeholder="Email">
                <p>Email is:  email </p>
            </div>
        </div>
    </div>
</template>

<script>
    import axios from 'axios';
    export default 
      mounted() 
          console.log('Component ready.');

          console.log(JSON.parse(this.a));
          console.log(JSON.parse(this.b));

          this.appliances = JSON.parse(this.a);
          this.brands = JSON.parse(this.b);

      ,

      props: ['a','b'],

        data: function() 
          return 
              appliances: '',
              appliance: '',
              brands: '',
              brand: '',
              age: '',
              first_name: '',
              last_name: '',
              phone_number: '',
              email: '',
              questions: '',
              answers: '',
              result: '',
              grouped_answers:'',
            
        ,
        methods: 
         getQuestions: function ()
           console.log(this.appliance);
           var self = this;
           axios.get('/get_questions/' + this.appliance, 

            )
            .then(function(response) 
                console.log(response.data);
                self.questions = response.data;
                self.getAnswers();
            )
            .catch(function(error) 
                console.log(error);
            );
         ,
         getAnswers: function ()
           console.log(this.appliance);
           var self = this;
           axios.get('/get_answers/' + this.appliance, 

              )
              .then(function(response) 
                  console.log(response.data);
                  self.answers = response.data;
                  self.putAnswers();
              )
              .catch(function(error) 
                  console.log(error);
              );
         ,
         putAnswers: function ()
           var result = ;

           for (var i = 0; i < this.answers.answers.length; i++) 
             var question_id = this.answers.answers[i].question_id;
             console.log(question_id);
             if(!result[question_id]) 
                result[question_id] = question_id: question_id, answers: [];
              
              result[question_id].answers.push(
                id: this.answers.answers[i].id,
                answer: this.answers.answers[i].answer)
           
           result = Object.keys(result).map(function (key)  return result[key]; );
           console.log(result);

           this.grouped_answers = result;

           console.log(this.grouped_answers[0].answers);

         ,
       ,
    
</script>

推荐后更新

        <div v-for="question in questions.questions">
          question.question
          <div v-for="a in grouped_answers[0].answers" v-if="grouped_answers">
            a.answer
          </div>
        </div>

【问题讨论】:

尝试在此处设置 v-if 指令 - &lt;div v-for="a in grouped_answers[0].answers" v-if="grouped_answers"&gt; 仍然有问题@BelminBedak,我已经用你的建议更新了我的答案 好的,我想getAnswers 方法是处理这些数据所必需的——但我看不出你在哪里调用这个方法?我认为它应该被称为created()mounted() 钩子。 您的控制台登录 putAnswers 是否返回任何内容? 是 putAnswers 方法处理从 axios get 请求的 .then 调用的数据。所有方法都在 .then 上起作用,因为在相应的 get 请求之后,该数据才可用。 【参考方案1】:

v-for 优先于v-if,因此它试图在有任何数据之前运行循环。为了防止这种情况,请添加一个周围的 div 或 span 并将 v-if 附加到它上面。比如:

    <div v-for="question in questions.questions">
      question.question
      <div v-if="grouped_answers">
        <div v-for="a in grouped_answers[0].answers">
          a.answer
        </div>
      </div>
    </div>

这里是他们提到优先级的文档:

https://vuejs.org/v2/guide/list.html#v-for-with-v-if

【讨论】:

以上是关于来自对象键和嵌套数组的 Vue.js v-for 循环的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js 从数组中弹出一个嵌套对象

使用 p 标签的嵌套 v-for 循环在 Vue.js 中不起作用

Vue.js v-for 在列表项上,通过 id 查找数组对象

Vue.js - 如何显示所有属性键和嵌套属性值?

如何在 Vue.js 中使用 v-for 遍历对象数组?

Vue.js - 如何按特定属性对数组中的对象进行排序并使用“v-for”进行渲染