一、需求说明
1.渲染功能
(1)代码
<!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" /><link rel="stylesheet" href="./css/inputnumber.css" /><link rel="stylesheet" href="./css/index.css" /><title>购物车</title>
</head>
<body>
<div class="app-container" id="app"><!-- 顶部banner --><div class="banner-box"><img src="img/fruit.jpg" alt="" /></div><!-- 面包屑 --><div class="breadcrumb"><span>🏠</span>/<span>购物车</span></div><!-- 购物车主体 --><div class="main" v-if="fruitList.length > 0"><div class="table"><!-- 头部 --><div class="thead"><div class="tr"><div class="th">选中</div><div class="th th-pic">图片</div><div class="th">单价</div><div class="th num-th">个数</div><div class="th">小计</div><div class="th">操作</div></div></div><!-- 身体 --><div class="tbody"><div v-for="(item, index) in fruitList" :key="item.id" class="tr" :class="{ active: item.isChecked }"><div class="td"><input type="checkbox" v-model="item.isChecked" /></div><div class="td"><img :src="item.icon" alt="" /></div><div class="td">{{ item.price }}</div><div class="td"><div class="my-input-number"><button class="decrease"> - </button><span class="my-input__inner">{{ item.num }}</span><button class="increase"> + </button></div></div><div class="td">{{ item.num * item.price }}</div><div class="td"><button>删除</button></div></div></div></div><!-- 底部 --><div class="bottom"><!-- 全选 --><label class="check-all"><input type="checkbox" />全选</label><div class="right-box"><!-- 所有商品总价 --><span class="price-box">总价 : ¥ <span class="price">24</span></span><!-- 结算按钮 --><button class="pay">结算( 6 )</button></div></div></div><!-- 空车 --><div class="empty" v-else>🛒空空如也</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {// 水果列表fruitList: [{id: 1,icon: 'img/火龙果.png',isChecked: true,num: 2,price: 6,},{id: 2,icon: 'img/荔枝.png',isChecked: false,num: 7,price: 20,},{id: 3,icon: 'img/榴莲.png',isChecked: false,num: 3,price: 40,},{id: 4,icon: 'img/鸭梨.png',isChecked: true,num: 10,price: 3,},{id: 5,icon: 'img/樱桃.png',isChecked: false,num: 20,price: 34,},],},})
</script>
</body>
</html>
(2)展示
2.删除和修改数量
(1)代码
<!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" /><link rel="stylesheet" href="./css/inputnumber.css" /><link rel="stylesheet" href="./css/index.css" /><title>购物车</title>
</head>
<body>
<div class="app-container" id="app"><!-- 顶部banner --><div class="banner-box"><img src="img/fruit.jpg" alt="" /></div><!-- 面包屑 --><div class="breadcrumb"><span>🏠</span>/<span>购物车</span></div><!-- 购物车主体 --><div class="main" v-if="fruitList.length > 0"><div class="table"><!-- 头部 --><div class="thead"><div class="tr"><div class="th">选中</div><div class="th th-pic">图片</div><div class="th">单价</div><div class="th num-th">个数</div><div class="th">小计</div><div class="th">操作</div></div></div><!-- 身体 --><div class="tbody"><div v-for="(item, index) in fruitList" :key="item.id" class="tr" :class="{ active: item.isChecked }"><div class="td"><input type="checkbox" v-model="item.isChecked" /></div><div class="td"><img :src="item.icon" alt="" /></div><div class="td">{{ item.price }}</div><div class="td"><div class="my-input-number"><button :disabled="item.num <=1" class="decrease" @click="sub(item.id)"> - </button><span class="my-input__inner">{{ item.num }}</span><button class="increase" @click="add(item.id)"> + </button></div></div><div class="td">{{ item.num * item.price }}</div><div class="td"><button @click="del(item.id)">删除</button></div></div></div></div><!-- 底部 --><div class="bottom"><!-- 全选 --><label class="check-all"><input type="checkbox" />全选</label><div class="right-box"><!-- 所有商品总价 --><span class="price-box">总价 : ¥ <span class="price">24</span></span><!-- 结算按钮 --><button class="pay">结算( 6 )</button></div></div></div><!-- 空车 --><div class="empty" v-else>🛒空空如也</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {// 水果列表fruitList: [{id: 1,icon: 'img/火龙果.png',isChecked: true,num: 2,price: 6,},{id: 2,icon: 'img/荔枝.png',isChecked: false,num: 7,price: 20,},{id: 3,icon: 'img/榴莲.png',isChecked: false,num: 3,price: 40,},{id: 4,icon: 'img/鸭梨.png',isChecked: true,num: 10,price: 3,},{id: 5,icon: 'img/樱桃.png',isChecked: false,num: 20,price: 34,},],},methods:{del(id){this.fruitList = this.fruitList.filter(item => item.id !== id)},add(id){//1.根据id 找到数组中的对应项 -> findconst fruit = this.fruitList.find(item => item.id === id)//2.操作num数量fruit.num++// console.log(id)},sub(id){//1.根据id 找到数组中的对应项 -> findconst fruit = this.fruitList.find(item => item.id === id)//2.操作num数量fruit.num--// console.log(id)}},})
</script>
</body>
</html>
(2)展示
减到1就不能再减,点击删除直接删除
3.全选与反选
(1)代码
<!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" /><link rel="stylesheet" href="./css/inputnumber.css" /><link rel="stylesheet" href="./css/index.css" /><title>购物车</title>
</head>
<body>
<div class="app-container" id="app"><!-- 顶部banner --><div class="banner-box"><img src="img/fruit.jpg" alt="" /></div><!-- 面包屑 --><div class="breadcrumb"><span>🏠</span>/<span>购物车</span></div><!-- 购物车主体 --><div class="main" v-if="fruitList.length > 0"><div class="table"><!-- 头部 --><div class="thead"><div class="tr"><div class="th">选中</div><div class="th th-pic">图片</div><div class="th">单价</div><div class="th num-th">个数</div><div class="th">小计</div><div class="th">操作</div></div></div><!-- 身体 --><div class="tbody"><div v-for="(item, index) in fruitList" :key="item.id" class="tr" :class="{ active: item.isChecked }"><div class="td"><input type="checkbox" v-model="item.isChecked" /></div><div class="td"><img :src="item.icon" alt="" /></div><div class="td">{{ item.price }}</div><div class="td"><div class="my-input-number"><button :disabled="item.num <=1" class="decrease" @click="sub(item.id)"> - </button><span class="my-input__inner">{{ item.num }}</span><button class="increase" @click="add(item.id)"> + </button></div></div><div class="td">{{ item.num * item.price }}</div><div class="td"><button @click="del(item.id)">删除</button></div></div></div></div><!-- 底部 --><div class="bottom"><!-- 全选 --><label class="check-all"><input type="checkbox" v-model="isAll"/>全选</label><div class="right-box"><!-- 所有商品总价 --><span class="price-box">总价 : ¥ <span class="price">24</span></span><!-- 结算按钮 --><button class="pay">结算( 6 )</button></div></div></div><!-- 空车 --><div class="empty" v-else>🛒空空如也</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {// 水果列表fruitList: [{id: 1,icon: 'img/火龙果.png',isChecked: true,num: 2,price: 6,},{id: 2,icon: 'img/荔枝.png',isChecked: false,num: 7,price: 20,},{id: 3,icon: 'img/榴莲.png',isChecked: false,num: 3,price: 40,},{id: 4,icon: 'img/鸭梨.png',isChecked: true,num: 10,price: 3,},{id: 5,icon: 'img/樱桃.png',isChecked: false,num: 20,price: 34,},],},computed:{//默认计算属性,只能能获取不能设置,要设置需要写完整写法// isAll(){// //必须所有的小选框都选中,全选按钮才选中 ——>every// return this.fruitList.every(item => item.isChecked)// },// 完整写法 => get+setisAll:{get(){return this.fruitList.every(item => item.isChecked)},set(value){//基于拿到的布尔值,要让所有的小选框 同步状态this.fruitList.forEach(item => item.isChecked = value)// console.log(value)},}},methods:{del(id){this.fruitList = this.fruitList.filter(item => item.id !== id)},add(id){//1.根据id 找到数组中的对应项 -> findconst fruit = this.fruitList.find(item => item.id === id)//2.操作num数量fruit.num++// console.log(id)},sub(id){//1.根据id 找到数组中的对应项 -> findconst fruit = this.fruitList.find(item => item.id === id)//2.操作num数量fruit.num--// console.log(id)}},})
</script>
</body>
</html>
(2)展示
4.统计选中的总价和总数量
(1)代码
<!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" /><link rel="stylesheet" href="./css/inputnumber.css" /><link rel="stylesheet" href="./css/index.css" /><title>购物车</title>
</head>
<body>
<div class="app-container" id="app"><!-- 顶部banner --><div class="banner-box"><img src="img/fruit.jpg" alt="" /></div><!-- 面包屑 --><div class="breadcrumb"><span>🏠</span>/<span>购物车</span></div><!-- 购物车主体 --><div class="main" v-if="fruitList.length > 0"><div class="table"><!-- 头部 --><div class="thead"><div class="tr"><div class="th">选中</div><div class="th th-pic">图片</div><div class="th">单价</div><div class="th num-th">个数</div><div class="th">小计</div><div class="th">操作</div></div></div><!-- 身体 --><div class="tbody"><div v-for="(item, index) in fruitList" :key="item.id" class="tr" :class="{ active: item.isChecked }"><div class="td"><input type="checkbox" v-model="item.isChecked" /></div><div class="td"><img :src="item.icon" alt="" /></div><div class="td">{{ item.price }}</div><div class="td"><div class="my-input-number"><button :disabled="item.num <=1" class="decrease" @click="sub(item.id)"> - </button><span class="my-input__inner">{{ item.num }}</span><button class="increase" @click="add(item.id)"> + </button></div></div><div class="td">{{ item.num * item.price }}</div><div class="td"><button @click="del(item.id)">删除</button></div></div></div></div><!-- 底部 --><div class="bottom"><!-- 全选 --><label class="check-all"><input type="checkbox" v-model="isAll"/>全选</label><div class="right-box"><!-- 所有商品总价 --><span class="price-box">总价 : ¥ <span class="price">{{ totalPrice }}</span></span><!-- 结算按钮 --><button class="pay">结算{{ totalCount }}</button></div></div></div><!-- 空车 --><div class="empty" v-else>🛒空空如也</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {// 响应式数据// 水果列表fruitList: [{id: 1,icon: 'img/火龙果.png',isChecked: true,num: 2,price: 6,},{id: 2,icon: 'img/荔枝.png',isChecked: false,num: 7,price: 20,},{id: 3,icon: 'img/榴莲.png',isChecked: false,num: 3,price: 40,},{id: 4,icon: 'img/鸭梨.png',isChecked: true,num: 10,price: 3,},{id: 5,icon: 'img/樱桃.png',isChecked: false,num: 20,price: 34,},],},computed:{// 计算属性//默认计算属性,只能能获取不能设置,要设置需要写完整写法// isAll(){// //必须所有的小选框都选中,全选按钮才选中 ——>every// return this.fruitList.every(item => item.isChecked)// },// 完整写法 => get+setisAll:{get(){return this.fruitList.every(item => item.isChecked)},set(value){//基于拿到的布尔值,要让所有的小选框 同步状态this.fruitList.forEach(item => item.isChecked = value)// console.log(value)},},// 统计选中的总数totalCount(){return this.fruitList.reduce((sum,item) => {if (item.isChecked){// 选中 -> 需要累加return sum +item.num} else {// 没选中 -> 不需要累加return sum}},0)},// 统计选中的总价totalPrice(){return this.fruitList.reduce((sum,item) => {if(item.isChecked){return sum + item.num * item.price}else{return sum}},0)},},methods:{del(id){this.fruitList = this.fruitList.filter(item => item.id !== id)},add(id){//1.根据id 找到数组中的对应项 -> findconst fruit = this.fruitList.find(item => item.id === id)//2.操作num数量fruit.num++// console.log(id)},sub(id){//1.根据id 找到数组中的对应项 -> findconst fruit = this.fruitList.find(item => item.id === id)//2.操作num数量fruit.num--// console.log(id)},},})
</script>
</body>
</html>
这里写三元表达式也可以
三元表达式是一种在许多编程语言中常见的条件表达式,它由三个操作数组成:一个条件表达式、一个真值表达式和一个假值表达式。其一般形式为:
condition ? expr1 : expr2
如果写成if...else
if (condition) {result = expr1;
} else {result = expr2;
}
三元写法
result = condition ? expr1 : expr2;
(2)展示
被勾选的被计算
5.持久化本地
如果用户对其操作之后 没有持久化刷新后就会成问题
(1)代码
<!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" /><link rel="stylesheet" href="./css/inputnumber.css" /><link rel="stylesheet" href="./css/index.css" /><title>购物车</title>
</head>
<body>
<div class="app-container" id="app"><!-- 顶部banner --><div class="banner-box"><img src="img/fruit.jpg" alt="" /></div><!-- 面包屑 --><div class="breadcrumb"><span>🏠</span>/<span>购物车</span></div><!-- 购物车主体 --><div class="main" v-if="fruitList.length > 0"><div class="table"><!-- 头部 --><div class="thead"><div class="tr"><div class="th">选中</div><div class="th th-pic">图片</div><div class="th">单价</div><div class="th num-th">个数</div><div class="th">小计</div><div class="th">操作</div></div></div><!-- 身体 --><div class="tbody"><div v-for="(item, index) in fruitList" :key="item.id" class="tr" :class="{ active: item.isChecked }"><div class="td"><input type="checkbox" v-model="item.isChecked" /></div><div class="td"><img :src="item.icon" alt="" /></div><div class="td">{{ item.price }}</div><div class="td"><div class="my-input-number"><button :disabled="item.num <=1" class="decrease" @click="sub(item.id)"> - </button><span class="my-input__inner">{{ item.num }}</span><button class="increase" @click="add(item.id)"> + </button></div></div><div class="td">{{ item.num * item.price }}</div><div class="td"><button @click="del(item.id)">删除</button></div></div></div></div><!-- 底部 --><div class="bottom"><!-- 全选 --><label class="check-all"><input type="checkbox" v-model="isAll"/>全选</label><div class="right-box"><!-- 所有商品总价 --><span class="price-box">总价 : ¥ <span class="price">{{ totalPrice }}</span></span><!-- 结算按钮 --><button class="pay">结算{{ totalCount }}</button></div></div></div><!-- 空车 --><div class="empty" v-else>🛒空空如也</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>const defaultArr = [{id: 1,icon: 'img/火龙果.png',isChecked: false,num: 1,price: 6,},{id: 2,icon: 'img/荔枝.png',isChecked: false,num: 1,price: 20,},{id: 3,icon: 'img/榴莲.png',isChecked: false,num: 1,price: 40,},{id: 4,icon: 'img/鸭梨.png',isChecked: false,num: 1,price: 3,},{id: 5,icon: 'img/樱桃.png',isChecked: false,num: 1,price: 34,},]const app = new Vue({el: '#app',data: {// 响应式数据// 水果列表fruitList: JSON.parse(localStorage.getItem('list')) || (defaultArr),},computed:{// 计算属性//默认计算属性,只能能获取不能设置,要设置需要写完整写法// isAll(){// //必须所有的小选框都选中,全选按钮才选中 ——>every// return this.fruitList.every(item => item.isChecked)// },// 完整写法 => get+setisAll:{get(){return this.fruitList.every(item => item.isChecked)},set(value){//基于拿到的布尔值,要让所有的小选框 同步状态this.fruitList.forEach(item => item.isChecked = value)// console.log(value)},},// // 统计选中的总数// totalCount(){// return this.fruitList.reduce((sum,item) => {// if (item.isChecked){// // 选中 -> 需要累加// return sum +item.num// } else {// // 没选中 -> 不需要累加// return sum// }// },0)// },// // 统计选中的总价// totalPrice(){// return this.fruitList.reduce((sum,item) => {// if(item.isChecked){// return sum + item.num * item.price// }else{// return sum// }// },0)// },//三元表达式// 统计选中的总数totalCount() {return this.fruitList.reduce((sum, item) => {return item.isChecked ? sum + item.num : sum;}, 0);},// 统计选中的总价totalPrice() {return this.fruitList.reduce((sum, item) => {return item.isChecked ? sum + item.num * item.price : sum;}, 0);},},methods:{del(id){this.fruitList = this.fruitList.filter(item => item.id !== id)},add(id){//1.根据id 找到数组中的对应项 -> findconst fruit = this.fruitList.find(item => item.id === id)//2.操作num数量fruit.num++// console.log(id)},sub(id){//1.根据id 找到数组中的对应项 -> findconst fruit = this.fruitList.find(item => item.id === id)//2.操作num数量fruit.num--// console.log(id)},},watch:{fruitList:{deep:true,handler(newValue){// 需要将变化后的newValue 存入本地 (转json)localStorage.setItem('list',JSON.stringify(newValue))}}}})
</script>
</body>
</html>
如果没有 || (defaultArr)清除缓存后就会null崩溃 ,加上之后就会默认回到初试页面了
(2)展示
6.总结
-----------------------------------------------------------------------------------------------------------------------------
注:本人是根据黑马程序员的B站教程来学习的,
链接:https://www.bilibili.com/video/BV1HV4y1a7n4/?spm_id_from=333.999.0.0
本文章仅仅是个人学习笔记 无任何其他用途 特此说明