五.循环遍历
1. v-for
- v-for 遍历数组
<div id="app">
<!-- 1.在遍历的过程中,不使用其索引值(下标) -->
<ul>
<li v-for="item in names">{{item}}</li>
</ul>
<!-- 2.在遍历过程中,想要获取其索引值index -->
<ul>
<li v-for="(item, index) in names">{{index+1}}.{{item}}</li>
</ul>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
names : ['zj', 'pdh']
}
})
</script>
- v-for 遍历对象
<!-- v-for 遍历对象 -->
<div id="app">
<!-- 1.遍历对象过程中,如果只是获取一个值,那么获取到的是value值 -->
<ul>
<li v-for="item in info">{{item}}</li>
</ul>
<!-- 2.想要同时获取key和value,格式为: (value,key) -->
<ul>
<li v-for="(value, key) in info ">{{value}}-{{key}}</li>
</ul>
<!-- 3.想要同时获取key,value和index,格式为: (value,key,index) -->
<ul>
<li v-for="(value, key,index) in info ">{{value}}-{{key}}-{{index}}</li>
</ul>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
info : {
name : 'pdh',
height : 1.88,
age : 18
}
}
})
</script>
- (拓展)响应式的数组方法:
方法 | 含义 |
---|---|
push() | 在数组最前面添加元素 |
pop() | 删除数组中的最后一个元素 |
shift() | 删除数组中的最后一个元素 |
unshift() | 在数组最前面添加元素 |
splice() | 删除元素/插入元素/替换元素 |
sort() | 排序 |
reverse() | 反转 |
- demo1 点击某行文字后,文字变成红色
<style>
.active {
color : red;
}
</style>
<body>
<div id="app">
<ul>
<li v-for="(item, index) in movies"
:class="{active: currentIndex === index}"
@click="liClick(index)">
<!-- 动态绑定class,当currentIndex=index时active为TRUE -->
{{index+1}}.{{item}}</li>
</ul>
</div>
<script src="./js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
movies: ['我不是药神', '喜羊羊与灰太狼之筐出未来','我讨厌异地恋','让子弹飞'],
currentIndex : 0 //记录状态
},
methods: {
liClick(index) {
this.currentIndex = index
}
},
})
</script>
</body>
六. 图书购物车案例
1.基本准备
- 构建表格基本样式,并将v-for遍历得到的数据渲染进表格内.
2.统一价格形式(两位小数且带有人民币符号)
- 方法一(在methods中构建getFinalPrice方法,需要时进行调用)
methods: {
getFinalPrice(price){
return '¥' + price.toFixed(2);
}
}
- 方法二(Vue中的过滤器filters,需要时在值右侧加‘ | 过滤器名 ’,如 item.price | showPrice)
filters : {
showPrice(price) {
return '¥' + price.toFixed(2);
}
}
3.改变购买数量(点击按钮使数值加减,当数值为1时无法点击减少按钮)
<td>
<button @click="decrement(index)" v-bind:disabled="item.count <= 1">-</button>
{{item.count}}
<button @click="increment(index)">+</button>
</td>
4.移除按钮(点击按钮移除该行数据,所有书籍均被移除后显示购物车为空)
- 点击按钮移除该行数据,删除书籍中的某一条数据
removeHandle(index){
this.books.splice(index,1)
}
- 所有书籍均被移除后显示购物车为空,即v-if=“books.length”,给整个table外套上一个div,并用v-if来进行判断,长度为零时,条件为false
<div id="app">
<div v-if="books.length">
<table>...</table>
</div>
<h2 v-else>购物车为空</h2>
</div>
5.显示最终价格 (计算属性)
computed: {
totalPrice() {
let totalPrice = 0;
for (let i = 0; i < this.books.length; i++){
totalPrice += this.books[i].price * this.books[i].count
}
return totalPrice
}
}
使用该计算属性时,再将价格用过滤统一成规定格式
<h2>总价格:{{totalPrice | showPrice}}</h2>
最终代码:
/* style.css */
table {
border: 1px solid #e9e9e9;
border-collapse: collapse;
}
th,td {
padding: 8px 16px;
border: 1px solid #e9e9e9;
text-align: left;
}
th {
background-color: #f7f7f7;
color: #5c6b77;
font-weight: 600;
}
// main.js
const app = new Vue({
el: '#app',
data: {
books : [
{
id : 1 ,
name : '《算法导论》',
date : '2006-9',
price : 85.50,
count : 1
},
{
id : 2 ,
name : '《JavaScript高级》',
date : '2002-9',
price : 95.50,
count : 1
},
{
id : 3 ,
name : '《计算机网络》',
date : '2006-9',
price : 45.50,
count : 1
},
{
id : 4 ,
name : '《数据结构》',
date : '2000-9',
price : 85.50,
count : 1
},
],
},
methods: {
// getFinalPrice(price){
// return '¥' + price.toFixed(2);
// }
increment(index){
this.books[index].count++
},
decrement(index){
this.books[index].count--
},
removeHandle(index){
this.books.splice(index,1)
}
},
computed: {
totalPrice() {
//1.普通的for循环
// let totalPrice = 0;
// for (let i = 0; i < this.books.length; i++){
// totalPrice += this.books[i].price * this.books[i].count
// }
// return totalPrice
//2.ES6中 for(let i in this.books) 拿到的i为索引值
// let totalPrice = 0;
// for(let i in this.books) {
// const book = this.books[i];
// totalPrice += book.price * book.count
// }
// return totalPrice
//3. for(let i of this.books)
// let totalPrice = 0;
// for(let item of this.books){
// totalPrice += item.price * item.count
// }
// return totalPrice
//4. reduce(高阶函数)
return this.books.reduce(function(preValue, book){
return preValue + book.price * book.count
},0)
}
},
filters : {
showPrice(price) {
return '¥' + price.toFixed(2);
}
}
})
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="app">
<div v-if="books.length">
<table>
<thead>
<tr>
<th></th>
<th>书籍名称</th>
<th>出版日期</th>
<th>价格</th>
<th>购买数量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in books">
<!-- 每一行需互不影响,故使用index来控制 -->
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date}}</td>
<!-- <td>{{getFinalPrice(item.price)}}</td> -->
<td>{{item.price | showPrice}}</td>
<td>
<button @click="decrement(index)" v-bind:disabled="item.count <= 1">-</button>
{{item.count}}
<button @click="increment(index)">+</button>
</td>
<td>
<button @click="removeHandle(index)">移除</button>
</td>
</tr>
</tbody>
</table>
<h2>总价格:{{totalPrice | showPrice}}</h2>
</div>
<h2 v-else>购物车为空</h2>
</div>
<script src="../vue.js"></script>
<script src="main.js"></script>
</body>
</html>
3.拓展:JS中高阶函数(filter,map,reduce)的使用
1. filter()的使用
- 语法:var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
- 注意:括号内为回调函数,必须返回一个布尔值,返回true时函数内部会将此次回调的n加入到新的数组,返回false时则会自动过滤此次的n,最终返回一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组
- 示例:
//打印数组中小于100的数
let newNums = nums.filter(function (n) {
return n < 100
})
console.log(newNums)
2.map()的使用
- 语法:
var new_array = arr.map(function callback(currentValue[, index[, array]]) { }[, thisArg])
- 注意:该方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。
- 示例:
//打印新数组所有元素值两倍的数组
let new2Nums = newNums.map(function (n) {
return n * 2
})
console.log(new2Nums)
3. reduce()的使用
- 作用:对数组中所有内容进行汇总
- 语法:(previousValue为前一次调用 callbackfn 得到的返回值,currentValue为数组中正在处理的元素,currentIndex为数组中正在处理的元素的索引)
// Inline callback function reduce(function(previousValue, currentValue) { /* ... */ }) reduce(function(previousValue, currentValue, currentIndex) { /* ... */ }) reduce(function(previousValue, currentValue, currentIndex, array) { /* ... */ }) reduce(function(previousValue, currentValue, currentIndex, array) { /* ... */ }, initialValue)
- 示例:
//将两倍数组内元素求和
let total = new2Nums.reduce(function (preValue, n) {
return preValue + n
},0)
console.log(total);
将以上高阶函数综合使用,直接得到最终结果
let total = nums.filter(function (n) {
return n < 100
}).map(function (n) {
return n * 2
}).reduce(function (preValue, n) {
return preValue + n
},0);
//箭头函数,结果相同
//let total = nums.filter(n => n < 100).map(n => n * 2).reduce((pre, n) => pre + n);
console.log(total);