这里以Vue.js创建一个简单的小回答测验项目quiz为案例,一步步从无到有展示Vue的使用。
安装
创建HTML主要骨架,并导入Vue:
<html> <body> <!-- Vue在这个div中起作用工作 --> <div id="app"> <!-- Vue的data.title 显示在这儿--> <h1>{{ title }}</h1> </div> <!-- Load Vue script --> < script src = " https://vuejs.org/js/vue.js " >< /script > <!-- On load, init Vue --> window.function(){ new Vue({ el: 'app', // Vue 工作在这个div data: { title: 'Hello.' }, // title设置为 'Hello.' }); } </body>
|
将其保存为foo.html,在浏览器打开,会看到Hello,这里我们学习了{{title}}语法渲染数据。Data数据
创建一个简单的quiz回答项目,带有一个标题和两个问题,每个问题有一个或多个答案,其中有多个可能答案正确。我们将其连接Vue的实例数据。
window.function(){ var quiz = { title: 'My quiz', questions: [ { text: "问题 1", responses: [ {text: '错误, too bad.'}, {text: '正确!', correct: true}, ] }, { text: "问题 2", responses: [ {text: '正确答案', correct: true}, {text: '回答错误'}, ] } ] }; new Vue({ el: 'app', data: { quiz: quiz }, // 连接quiz 到 Vue data }); }
|
设置好基本回答问题后,下一步如何使用Vue loops循环输出。
在Html渲染数据
Vue提供指令驱动循环系统将数据加入HTML:v-for=”item on items”:
<div id="app"> <!-- Quiz title --> <h1>{{ quiz.title }}</h1> <!-- questions: 为questions中每个question用div显示输出 --> <div v-for="question in quiz.questions"> <h2>{{ question.text }}</h2> <!-- Responses: display a li for each possible response with a radio button --> <ol> <li v-for="response in question.responses"> <label> <input type="radio"> {{response.text}} </label> </li> </ol> </div> </div>
|
这里有一个不显眼的响应式reactive系统,如果数据对象改变,HTML试图会更新,现在quiz这个项目的所有问题都已经显示,它是活动的及时更新的,是积极响应的。导航
现在这个项目中所有问题显示在一个页面上,那我们改一下,每个页面显示一个问题,需要在每个问题页面上增加next(上一页)和previous(下一页)。隐藏所有不不是当前问题的其他问题。
我们创建的app能够处理用户输入:按钮点按,首先,增加当前问题索引数据和两个导航方法到Vue实例:
new Vue({ el: 'app', data: { quiz: quiz, // 存储当前问题索引Store current question index questionIndex: 0, }, // 当点按按钮时,视图会触发这些方法 methods: { // Go to next question 到下一个问题 next: function() { this.questionIndex++; }, // Go to previous question到上个问题 prev: function() { this.questionIndex--; } } });
|
questionIndex 会在next()增加,而在prev()调用是减少。下面创建Html导航按钮触发上面两个方法,使用v-on:click=”next”指令触发next();使用v-show=”index === questionIndex”显示当前问题,不要忘记将index索引加入v-for中。
<div id="app"> <h1>{{ quiz.title }}</h1> <!-- index is used to check with current question index --> <div v-for="(question, index) in quiz.questions"> <!-- 隐藏不是当前问题的其他问题,只显示索引对应的问题 --> <div v-show="index === questionIndex"> <h2>{{ question.text }}</h2> <ol> <li v-for="response in question.responses"> <label> <input type="radio"> {{response.text}} </label> </li> </ol> <!-- 两个导航按钮 --> <!-- Note: prev is hidden on first question --> <button v-if="questionIndex > 0" v-on:click="prev"> prev </button> <button v-on:click="next"> next </button> </div> </div> </div>
|
现在我们可以进入这个问答项目。最后一页是空白的,我们应该显示测验结果在它。
Quiz结果
要显示一个评分结果,我们必须处理每个问题的用户响应。这是最难的一步。
目前radio 按钮没有绑定Vue,点按radio 没有效果,v-model实现表单输入和应用状态两者双向绑定,使用下面radio 替代之前的:
<!-- for each response of the current question --> <li v-for="response in question.responses"> <label> <!-- The radio button has three new directives --> <!-- v-bind:如果回答正确设置 "value" 为 "true"--> <!-- v-bind:n设置 "name" 到问题索引,指向问题一组答案中一个--> <!-- v-model 和userResponses 绑定--> <input type="radio" v-bind:value="response.correct" v-bind:name="index" v-model="userResponses[index]"> {{response.text}} </label> </li>
|
name和value被绑定到Vue数据,然后在Vue实例初始化userResponses :
new Vue({ el: 'app', data: { quiz: quiz, questionIndex: 0, // 数组为每个问题初始值为 "false" // 意思是: "用户正确回答这个问题吗?" "no". userResponses: Array(quiz.questions.length).fill(false) }, methods: { // ... } });
|
这是为了处理用户响应的最后一步:userResponses包含一个数组,你可以向前和向后导航,选择和更改答案,会发现userresponses“自己更新”。创建方法进行分数计算:
new Vue({ // ... methods: { // ... // 返回 在userResponses中"true" 数量 score: function() { return this.userResponses.filter(function(val) { return val }).length; } } });
|
增加下面最后一页显示总分:
<div id="app"> <h1>{{ quiz.title }}</h1> <div v-for="(question, index) in quiz.questions"> <!-- //... --> </div> <!-- Last page, quiz is finished, display result --> <div v-show="questionIndex === quiz.questions.length"> <h2> Quiz finished </h2> <p> Total score: {{ score() }} / {{ quiz.questions.length }} </p> </div> </div>
|
最后项目完成,可在这里演示。源码这里
原文:
Create a quiz with Vue.js – Medium
[该贴被banq于2016-11-03 11:09修改过]