表格的 v-for列表渲染
<table border="1">
<tr><!-- 表格第一排 -->
<th>#</th>
<th>课程</th>
<th>单价</th>
<th>数量</th>
<th>总价</th>
</tr>
<tr v-for="(c,index) in cart" :key="c.id"><!-- 表格第二排v-for进行列表渲染 -->
<td>
<input type="checkbox" v-model="c.active" />
</td>
<td>{{c.title}}</td>
<td>{{c.price}}</td>
<td>
<button @click="substruct(index)">-</button>
{{c.count}}
<button @click="add(index)">+</button>
</td>
<td>¥{{c.price * c.count}}</td><!-- 表格内直接写表达式:单价×数量 -->
</tr>
<tr><!-- 表格v-for列表渲染下方插入自定义表格内容 - 应该不常用 -->
<td></td>
<td colspan="2">{{activeCount}}/{{count}}</td>
<td colspan="2">{{total}}</td>
</tr>
</table>
购买数量加减按钮 和清零后提示删除弹出消息
methods: {
remove(index) {
if (window.confirm("是否确定要删除?")) {
this.cart.splice(index, 1);
}
},
substruct(index) {
let count = this.cart[index].count;
count > 1 ? (this.cart[index].count -= 1) : this.remove(index);
},
add(index) {
this.cart[index].count++;
}
}
显示 已选择/全部
通过filter方法来筛选出已选择,length获取筛选后的长度
computed: {
count() {
return this.cart.length;
},
activeCount() {
return this.cart.filter(v => v.active).length;
}
}
计算属性 已选择的总价格
方法一 :forEach遍历方法
forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数
total() {
let sum = 0;//赋值初始值为0
this.cart.forEach(c => {
if (c.active) {//筛选并返回所有active为true的对象
sum += c.price * c.count;//将所有返回的对象进行计算合计
}
});
return sum;
}
方法二 :数组的reduce方法
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值
total() {
return this.cart.reduce((sum, c) => {
if (c.active) {//筛选c数组内,active为true的对象
sum += c.price * c.count;//从前向后累加计算
}
return sum;
}, 0);//0传入对sum赋予初始值
}
购物车实例:
main.js:
import Axios from 'axios'//引入axios
Vue.prototype.$http = Axios;//为实例挂载Axios
Vue.prototype.$bus = new Vue();//创建中央事件总线实例
父组件:
<template>
<div id="app">
<h2>{{title}}</h2>
<ul>
<!-- 2.v-for列表渲染cartList -->
<li v-for="(item,index) in cartList" :key="item.id">
<h3>{{item.title}}</h3>
<p>价格:¥{{item.price}}</p>
<button @click="addCart(index)">添加购物车</button>
<!-- 3.绑定点击事件触发addCart方法 -->
</li>
</ul>
<MyCart></MyCart>
</div>
</template>
<script>
import MyCart from "./components/Cart.vue";
export default {
name: "App",
data() {
return {
cartList: [],
title: "宝贝展示"
};
},
methods: {
addCart(i) {
const good = this.cartList[i]; //获取点击的数据
this.$bus.$emit("addCart", good); //4.触发$bus内的addCart方法,并传入good数据
}
},
async created() {
try {//1.组件创建完成立即ajax请求获取数据并赋值给cartList
const res = await this.$http.get("api/cartList");
this.cartList = res.data.result;
} catch (error) {
console.log(error);
}
},
components: {
MyCart
}
};
</script>
<style scoped>
ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
width: 500px;
justify-content: space-between;
margin-bottom: 50px;
}
</style>
子组件:
<template>
<div>
<h2>{{title}}</h2>
<table border="1">
<tr>
<th>#</th>
<th>课程</th>
<th>单价</th>
<th>数量</th>
<th>总价</th>
</tr>
<!-- 9.列表渲染获取到的cart数据 -->
<tr v-for="(c,index) in cart" :key="c.id">
<td>
<input type="checkbox" v-model="c.active" />
</td>
<td>{{c.title}}</td>
<td>{{c.price}}</td>
<td>
<!-- 10.绑定点击事件并传值当前数据对象index -->
<button @click="substruct(index)">-</button>
{{c.count}}
<button @click="add(index)">+</button>
</td>
<td>¥{{c.price * c.count}}</td>
</tr>
<tr>
<td></td>
<td colspan="2">{{activeCount}}/{{count}}</td>
<td colspan="2">¥{{total}}</td>
</tr>
</table>
</div>
</template>
<script>
export default {
name: "cart",
data() {
return {
title: "购物车",
//8.刷新页面后,获取本地json数据cart并转换为js对象,对实例内cart赋值,如果没有本地数据,赋值为空数组
cart: JSON.parse(localStorage.getItem("cart")) || [];
};
},
watch: {
cart: {
//6.深度监听cart数据变化,调用setLocalData方法并转入新值
deep: true,
handler(newV) {
this.setLocalData(newV);
}
}
},
created() {
this.$bus.$on("addCart", good => {
//5.监听$bus,获取被点击的对象数据判断赋值给cart,还是当前.count +1
const ret = this.cart.find(v => v.id === good.id);
if (!ret) {
//没有这条购物车数据,将good数据推入cart数组
this.cart.push(good);
} else {
//有的话 count +1
ret.count += 1;
}
});
},
methods: {
setLocalData(newV) {
//7.接收新值,转换为json字符串,并保存到本地数据 cart
localStorage.setItem("cart", JSON.stringify(newV));
},
remove(index) {
//12.值为0,删除数组内当前对象
if (window.confirm("是否确定要删除?")) {
this.cart.splice(index, 1);
}
},
substruct(index) {
//11.购物车内的-1按钮,判断值是否大于1,大于1修改对应对象内count,值等于1时点击执行remove方法
let count = this.cart[index].count;
count > 1 ? (this.cart[index].count -= 1) : this.remove(index);
},
add(index) {
//购物车内的+1按钮
this.cart[index].count++;
}
},
computed: {
count() {
return this.cart.length;
},
activeCount() {
return this.cart.filter(v => v.active).length;
},
total() {
return this.cart.reduce((sum, c) => {
if (c.active) {
sum += c.price * c.count;
}
return sum;
}, 0);
}
}
};
</script>
<style scoped>
table {
width: 500px;
vertical-align: middle;
text-align: center;
user-select: none;
}
</style>