思路:
- 通过VueResource获取后台数据,浏览器控制台调试是否获取成功,用钩子函数mounted,确保当所有DOM挂载在页面上时,再请求
- 写好页面布局,设置接口,通过v-for实现页面渲染
- 通过filters过滤器实现渲染的数据格式化
- 实现商品数量加减功能(通过判断函数传参【-1,1】即可快速做到),同时控制数量最小只能减到1
- 实现选择商品功能,$set添加一个属性记录商品是否被选中状态,通过控制类名改变样式,实现 选择状态图标 的改变
- 实现全选和全取消功能,.forEach遍历商品列表,每个加上$set创造出的被选择状态或未被选择状态
- 计算结账总价格。每次计算前必须清0,遍历商品列表,每次计算(数量*单价),再商品相加
- 删除商品,用indexOf判断出已选择的商品位置,用splice 把商品从商品列表中删除。
知识点:
代码加详细注释vue文件:
<template>
<div>
<h1>购物车{{test}}</h1>
<div>
<ul v-for="item in productList">
<!-- {'checked':item.ischecked} 通过布尔动态改变类名 -->
<li class="select" :class="{'checked':item.ischecked}" @click="selectedItem(item)" ></li>
<li><img :src="item.productImage" alt=""></li>
<li>{{item.productName}}</li>
<li>{{item.productPrice|chineseYuan('元')}}</li>
<li class="inp">
<a href="javascript:;" @click="changeQuantity(item,-1)">-</a>
<input type="text" v-model="item.productQuantity">
<a href="javascript:;" @click="changeQuantity(item,1)">+</a>
</li>
<li>{{item.productPrice*item.productQuantity|chineseYuan('元')}}</li>
<li @click="removeConfirm(item)">删除</li>
</ul>
<div class="footer">
<div class="select" :class="{'checked':selectedAll}" @click="checkAll(true)" ></div>|
<span>全选</span>|
<span @click="checkAll(false)">全取消</span>|
<span>总金额:{{totalMoney}}</span>
</div>
</div>
<!-- 弹框 -->
<div class="alert" v-show="showto" style="background-color:white; position:absolute ;top:40%;left: 40%; width:300px;z-index:51;">
<div class="md-modal-inner">
<div class="md-top">
<button class="md-close" @click="showto=false">关闭</button>
</div>
<div>
<div>
<p>你确认删除此订单信息吗?</p>
</div>
<div>
<button @click="removeClass">Yes</button>
<button @click="showto=false">No</button>
</div>
</div>
</div>
</div>
<div class="shade" v-show="showto" style="width:1000px; height:1000px;position:fixed; top :0px;background-color:#000;opacity:0.1;text-align:center;z-index:10;"></div>
</div>
</template>
<style>
div{
width:80%;
margin: 0 auto;
}
.footer{
width:1200px;
}
.footer>div{
display: inline-block;
}
ul{
list-style-type: none;
margin:0;
padding:0;
display: flex;
}
li{
display: inline;
width:12%;
justify-content: space-between;
}
li input{
width: 60%;
text-align: center;
}
.select{
width:20px;
height: 20px;
background-image:url(img/notselect.png);
background-repeat: no-repeat;
background-size: 90%;
}
.checked{
background-image:url(img/selects.png);
}
.inp a{
margin: auto 5px;
text-decoration: none;
font-size: 15px;
}
</style>
<script>
export default{
data:function(){
return{
test:'testtesttest',
productList:[],
totalMoney:0,
selectedAll:false,
deleteClass:false,
currenClass:'',
showto:false
}
},
filters:{
//Vue 2.0瘦身了很多自带filter,能用原生写的全部清理掉
chineseYuan:function(value,param){
if(!value) return '0';
return '¥ ' + value.toFixed(2)+param;//真正项目中需要后代反馈金额,JS会导致金额误差
}
},
//钩子函数,当所有DOM挂载在页面上时,加载此方法,相当于window.onload=function(){}
mounted:function(){
//需要用$nextTick来保证所有节点挂载后才执行方法
this.$nextTick(function(){
this.cartView();
})
},
methods:{
cartView:function(){
var _this = this;
//Vue.source插件,目前已经被axios代替
// this.$http.get('./public/data/cartData.json',{'id':123}).then(function(res) ?????为何只能请求不到public文件内容
this.$http.get('./data/cartData.json',{'id':123}).then(function(res){
_this.productList = res.data.result.list;
console.log(res)
// _this.totalMoney = res.data.result.totalMoney;
});
},
changeQuantity:function(product,type){
if (type>0) {
//加号增加数量
product.productQuantity++;
this.calcTotalmoney();//数量变动重新计算总金额
} else{
//减号减少数量,但是因为有删除按钮所以最小数量为1
if(product.productQuantity < 2){
product.productQuantity = 1;
}else{
product.productQuantity--;
this.calcTotalmoney();//数量变动重新计算总金额
}
}
},
selectedItem:function(item){
if(typeof item.ischecked === 'undefined'){
//局部$set方法,在item里注册ischecked属性,赋值为true
this.$set(item,'ischecked',true);
}else {
//点击反转属性值
item.ischecked = !item.ischecked;
};
this.calcTotalmoney();//选择商品重新计算总金额
},
checkAll:function(statu){
//根据传参决定是全选还是取消全选
this.selectedAll = statu;
var _this = this;//用ES5方法解决this指向问题
//forEach(),val为数据的每一项,index为每一项的索引
this.productList.forEach(function(val,index){
//同样的,因为json内没有确定是否选择的属性,我们需要自己创建一个表示每一项商品是否被选择的属性,
//通过局部注册来注册data里的每一项商品的ischecked属性。
if(typeof val.ischecked === 'undefined'){
_this.$set(val,'ischecked',_this.selectedAll);
}else {
val.ischecked = _this.selectedAll;
}
});
this.calcTotalmoney();// 全选/非全选 商品重新计算总金额
},
calcTotalmoney:function(){
var _this = this;//用ES5方法解决this指向问题
//每次计算前必须清理,防止出现累计计算
this.totalMoney = 0;
this.productList.forEach(function(val,index){
if(val.ischecked){
_this.totalMoney += val.productPrice * val.productQuantity;
}
});
},
removeConfirm:function(item){
this.showto = true;
this.currentClass = item;
},
removeClass:function(){
//indexOf方法接受一个值,在数组中进行检索这个值是否存在,这个值可以使字符串、数字、和对象
var index = this.productList.indexOf(this.currentClass);
this.productList.splice(index,1);
this.deleteClass = false;
this.calcTotalmoney();//删除商品后重新计算总金额
}
}
}
</script>