复选框状态不会保留在简单的vue.js问卷调查应用中

时间:2017-03-07 17:48:53

标签: javascript checkbox vue.js frontend reactive-programming

我写了这个简单的问卷调查应用示例:https://jsfiddle.net/neydmo34/但是当用户点击“下一步”和“返回”按钮时,我的问题是复选框失去状态。

例如,如果用户执行此操作:

  1. 在第一个问题上回答“Lisp”,
  2. 点击“下一步”,
  3. 在第二个问题上回答“比尔盖茨”,
  4. 点击“返回”,
  5. 点击“下一步”,
  6. 然后你会看到“比尔盖茨”复选框不再被选中,尽管支持数组userAnswers已正确更新。

    我无法理解为什么会发生这种情况以及我应该在代码中更改以使其正常工作。

    以下是代码:

    <html>
    <head>
    <title>Questionnaire</title>
    <script src="vue.js"></script>
    </head>
    <body>
    <h1>Questionnaire</h1>
    <div id="app">
      <p><b>Question {{ currQuestionIndex + 1 }})</b> {{ currQuestion.text }}</p>
      <div v-for="ans in currQuestion.answers">
        <input type="radio"
               :name="currQuestionIndex"
               :value="ans"
               v-model="userAnswers[currQuestionIndex]" />
        <label :for="ans">{{ ans }}</label><br>
      </div>
      <p>
      <button @click="goBack">Back</button>
      <button @click="goNext">Next</button>
      </p>
      userAnswers = {{ userAnswers }}
    </div>
    </body>
    <script>
    var app = new Vue({
      el: '#app',
      data: {
        currQuestionIndex: 0,
        questions: [
            {text: "What's the name of most powerful programming language?",
             answers: ['Java', 'C#', 'Lisp', 'Haskell']
            },
            {text: 'Who is Microsoft founder?',
             answers: ['Bill Gates', 'Richard Stallman', 'Steve Jobs']
            },
            {text: 'What type of software do you like most?',
             answers: ['open source', 'closed source', 'public domain']
            },
            {text: 'The best computing company is:',
             answers: ['IBM', 'Microsoft', 'Google']
            },
        ],
    
        userAnswers: [null, null, null, null]
      },
    
      computed: {
        currQuestion: function () {
            return this.questions[this.currQuestionIndex];
        }
      },
    
      methods: {
        goNext: function(e) {
            var next = this.currQuestionIndex + 1;
            if (next >= this.questions.length) {
                alert("Ok, your answers are: " + this.userAnswers);
            } else {
                this.currQuestionIndex = next;
            }
        },
        goBack: function(e) {
            var previous = this.currQuestionIndex - 1;
            if (previous >= 0) {
                this.currQuestionIndex = previous;
            }
        }
      }
    });
    </script>
    </html>
    

1 个答案:

答案 0 :(得分:2)

var app = new Vue({
  el: '#app',
  data: {
    currQuestionIndex: 0,
    questions: [
        {text: "What's the most powerful programming language?",
         answers: ['Java', 'Scheme', 'Lisp', 'Haskell']
        },
        {text: 'Who is Microsoft founder?',
         answers: ['Bill Gates', 'Richard Stallman', 'Steve Jobs']
        },
        {text: 'What type of software do you like most?',
         answers: ['open source', 'closed source', 'public domain']
        },
        {text: 'The best computing company is:',
         answers: ['IBM', 'Microsoft', 'Google']
        },
    ],
    
    userAnswers: [null, null, null, null]
  },
  
  computed: {
    currQuestion: function () {
        return this.questions[this.currQuestionIndex];
    }
  },
  
  methods: {
    goNext: function(e) {
        var next = this.currQuestionIndex + 1;
        if (next >= this.questions.length) {
            alert("OK, your answers are: " + this.userAnswers);
        } else {
            this.currQuestionIndex = next;
        }
    },
    goBack: function(e) {
        var previous = this.currQuestionIndex - 1;
        if (previous >= 0) {
            this.currQuestionIndex = previous;
        }
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script>
<h1>Questionnaire</h1>
<div id="app">
  <p><b>Question {{ currQuestionIndex + 1 }})</b> {{ currQuestion.text }}</p>
  <div v-for="ans in currQuestion.answers" :key="ans">
    <input type="radio" :name="currQuestionIndex" :value="ans" v-model="userAnswers[currQuestionIndex]" />
    <label :for="ans">{{ ans }}</label><br>
  </div>
  <p>
  <button @click="goBack">Back</button>
  <button @click="goNext">Next</button>
  </p>
  userAnswers = {{ userAnswers }}
</div>

You need a key

  

当Vue更新使用v-for呈现的元素列表时,它依次为   默认使用“就地补丁”策略。如果是数据的顺序   项已更改,而不是移动DOM元素以匹配   物品的顺序,Vue将简单地修补每个元素和   确保它反映了应该在该特定情况下呈现的内容   指数。这类似于Vue中track-by="$index"的行为   1.x的。

     

此默认模式是高效的,但只有当列表呈现输出不依赖于子组件状态或临时DOM时才适合   状态(例如表单输入值)。

     

给Vue一个提示,以便它可以跟踪每个节点的身份,从而   重用和重新排序现有元素,您需要提供唯一的key   每个项目的属性。

由于每个答案在您的表单中都是唯一的,因此您可以使用:key="ans"

更新:添加了从Cristy小提琴中复制的片段。