相信大家在做电商网站的时候,最常见印象最深当属购物车了,有了它我们才可以统计客户选购的商品,然后进行下面收款发货功能,那么购物车这个功能,我们应该怎样通过js给他实现呢,下面让我通过本地存储给大家模仿一个简易的购物车功能吧。

首先我们先分析一下,购物车的前提是需要有一个商城,它包含很多的商品,任由我们来选择,然后当我们点击购物车时,购物车里会显示我们刚刚选择的商品数据。所以我们分两部分来写,首先简单写一个商城把。

一.商城

html部分
<h2>欢迎来到商城,请选购商品   <a href="购物车.html">点击进入购物车</a></h2>
<div class="cont"></div>

css部分
.cont{width: 1000px;margin: 30px auto;border: 1px solid black;overflow: hidden;}
.cont .goods{width:250px;float: left;border: 1px solid black;box-sizing: border-box;text-align: center;}
.goods img{width: 80%;}
.goods span{display: block;margin: 10px 0;}
.goods p{height: 40px;line-height: 20px;overflow: hidden;}
.goods input{display: block;margin: 0 auto;font-size: 20px;}

js部分
1.我们事先准备一个数组,把我们一些商品的数据储存起来,这样的好处,有利于我们以后对于商品数据的添加和更换

//定义一个商品数组
		var data = [{
        img:"https://img12.360buyimg.com/n7/jfs/t1/94329/20/12711/106212/5e4a97bcE66a103ae/721ae0eaf9ecbaa7.jpg",
        price:"1999.00",
        name:"荣耀20S 李现同款 3200万人像超级夜景 4800万超广角AI三摄 麒麟810 全网通版6GB+128GB 蝶羽蓝",
        goodsId:"123asd"
    },{
        img:"https://img10.360buyimg.com/n7/jfs/t1/93499/17/90/221850/5da6d4ebE9747a490/8b167328e1dadff8.jpg",
        price:"2199.00",
        name:"【品质好物】5000mAh大电量,支持18W快充,Type-C充电接口!【K305G爆品开售,点击选购】",
        goodsId:"ajgjgj"
    },{
        img:"https://img12.360buyimg.com/n7/jfs/t1/103980/26/12527/248017/5e4a6b2bEde93b893/af9f1eb0617ce599.jpg",
        price:"2399.00",
        name:"这是一个手机,看着像手机就行,这是名字",
        goodsId:"12u3"
    },{
        img:"https://img10.360buyimg.com/n7/jfs/t11266/172/3136897597/311385/898550cb/5ce41430N7bb10f75.jpg",
        price:"1899.00",
        name:"这也是个手机,这是这个手机的名字",
        goodsId:"afa876"
    }];

2.接下来我们需要的就是把这些数据,放在我们一开始定义的盒子里,完成一个商品展示的效果。

class GoodsList{
//  	1.构造函数
    	constructor(){
    		this.data = data;
    		this.cont = document.querySelector(".cont");
    	}
    	//  2.事件绑定
        init(){
//      	3.准备一个空字符串
    	  var str = "";
    	  for(var i = 0;i<this.data.length;i++){
//  	  	4.通过遍历商品数组,把商品属性添加到空数组中
    	  	str += `<div class="goods" index="${this.data[i].goodsId}">
                            <img src="${this.data[i].img}" alt="">
                            <span>${this.data[i].price}</span>
                            <p>${this.data[i].name}</p>
                            <input type="button" value="加入购物车" class="add">
                     </div>`
    	  }
//  	  5.把商品添加后在大框中显示
    	  this.cont.innerHTML = str;
        }

直到这里我们可以先创建一个实例对象,来看看我们的效果。

//  6.可以先创建实例对象查看
    var gl = new GoodsList();
    gl.init();
    gl.addEvent();

购物车怎么设计 redis缓存_javascript


这样我们一个初始的商城雏形就出来了,我们再进行一下分析:

既然我们需要通过点击商品到购物车,我们通过每个商品不同的id,方便把不同的商品进行分开区别。然后当点击商品后,存储在本地数据,进行判断如果本地存储中已经有了这个商品的数据,我们可以不需要再次获得它的数据,我们只需要的是把对应商品的数量+1即可。如果没有点击过此商品,我们就可以通过获取商品的数据在本地存储。

//      7.准备点击购买商品时,把数据本地储存
//      7.1因为事先大框中没有input元素,现在我们需要点击购买按钮,所以需要事件委托的方法
         addEvent(){
         	    var that = this;
         	    this.cont.onclick = function(eve){
         		var e = eve || window.event;
         		var tar = e.target ||e.srcElement;
//       		7.2判断如果选择到input元素,获取它的父元素的属性“index";
         		if(tar.className == "add"){
         			that.goodsId = tar.parentNode.getAttribute("index");
//              7.3开始进行本地存储数据
                 that.setData();
         		}
         	}
         }
         
//       8.本地存储数据
         setData(){
//       	8.1读取goodsMsgs数据
         	var gm = localStorage.getItem("goodsMsg");
//       	8.2判断本地是否有这个数据(数据所在的数组),没有那么就存储
            if(gm == null){
//          8.3没有就创建	
               gm = [{
               	goodsId:this.goodsId,
               	num:1,
               	msg:this.getData(this.goodsId)               	
               }]
            }
            else{
//          	8.4把数组json变成对象类型,方便直接获取属性
                gm = JSON.parse(gm);
                var zhuangtai = 0;
//              8.5判断存入的数据是否在数组中有,有的话加数量,没有的话把这个数据放到数组中
                for(var i = 0;i<gm.length;i++){
                	if(gm[i].goodsId == this.goodsId){
                		gm[i].num++;
                		zhuangtai = 1;
                		break;
                	}
                }
//             8.6 表示数组中没有此数据,添加进去
                if(zhuangtai == 0){
                	gm.push({
                		goodsId:this.goodsId,
                        num:1,
//                     8.7 通过传入的goodsid在getData()方法中,如果传入的数据=对应数据的id,那么就把对应的数据拿过来
                        msg:this.getData(this.goodsId)
                	})
                }
            }
            //9.以上这个if里面只是在判断操作获取到的数据,并没有存回去,所以最终操作完之后,需要将数据存到本地存储中
            localStorage.setItem("goodsMsg",JSON.stringify(gm));
         }
         
//      主要的作用是可以通过点击对应商品,获取商品id,然后遍历整个数据然后找到对应id所贮备的数据 
//        // 单独封装为了方便获取所有数据中,某个数据的功能
//       // 根据传入的id获取
         getData(id){
         	//遍历的时候,比较,符合,返回这个数据(判断是否有这个数据)
         	for(var i = 0;i<this.data.length;i++){
         		if(this.data[i].goodsId ==id){
         			return this.data[i];
         		}
         	}
         	//没有符合,返回空对象,保持数据格式一致
         	return {};
         }
//       
    }

做到这步的时候我们可以测试一下,看点击商品时,是否能达到我们预想的效果,看本地存储中是否有我们的数据。

购物车怎么设计 redis缓存_数组_02


一开始我们并没有数据,所以我们需要点击进行存储。

购物车怎么设计 redis缓存_javascript_03


当我们把商品加入购物车时,我们本地存储中已经有了我们每个商品对应的数据,而且当多次点击一个商品时,也并没有重新获取其数据,而是把对应的数量进行了叠加,此时我们商场的效果已经做到了,接下来就是进行购物车功能实现。

二、购物车

html部分
<h2>这是购物车   <a href="商城商品展示.html">点击返回商城</a></h2>
		<table border=1 width = 800px align = "center">
		<thead>
            <tr>
                <th>图片</th>
                <th>名字</th>
                <th>单价</th>
                <th>数量</th>
                <th>总价</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
        </tbody>	
		</table>

css部分
img{width: 100px;height: 100px;}

分析:需要满足购物车功能,我们首先做得就是需要拿到用户已经准备买的商品,也就是我们需要拿到本地存储中的数据,然后将其展现到页面上形成一个初步的雏形。

class Car{
//			1.构造函数
			constructor(){
				this.tbody = document.querySelector("tbody");
			}
//			2.从本地存储中拿到数据,准备在购物车页面显示
            getData(){
//          	2.1 立即拿到数据
                if(localStorage.getItem("goodsMsg")){
//              	2.2把其变为json对象格式,方便于调用其中的属性
                	this.gm = JSON.parse(localStorage.getItem("goodsMsg"));
                }
                else{
                	this.gm = [];
                }
                //3.准备渲染页面
                this.display();
            }
            display(){
//          	3.1 准备一个空字符串
            	var str = "";
//          	3.2把数据填入字符串中,准备放到页面上
            	for(var i=0;i<this.gm.length;i++){
                str += `<tr index="${this.gm[i].goodsId}">
                            <td><img src="${this.gm[i].msg.img}" alt=""></td>
                            <td>${this.gm[i].msg.name}</td>
                            <td>${this.gm[i].msg.price}</td>
                            <td><input type="number" min="1" value="${this.gm[i].num}" class="number"></td>
                            <td>${ this.gm[i].msg.price * this.gm[i].num }</td>
                            <td class="delete">删除</td>
                        </tr>`;
            }
//          	3.3渲染	
                this.tbody.innerHTML = str;
            }
		}

我们创建一个实例对象来看一下初步效果

//4.先创建实例对象进行页面查看
		var c = new Car();
		c.getData();

购物车怎么设计 redis缓存_数组_04


接下来就可以对我们的功能进行一下补充和完善。

功能1:删除功能
可以想到,当我们的用户发现错点了商品时,这时需要把购物车中的错误商品给删除掉,这时,我们需要做的就是在界面上去掉错误商品的显示,以及把存储在本地存储的数据给删除掉。

//事件绑定
            addEvent(){
               	var that = this;
//             4.删除功能
//             4.1因为我们一开始在html中并没有删除,所以需要用到事件委托
                this.tBody.onclick = function(eve){
                	var e = eve || window.event;
                	var tar = e.target || e.srcElement;
                	if(tar.className == "delete" ){
                		// 4.2先获取当前点击删除按钮的商品的id
                		that.id = tar.parentNode.getAttribute("index");
//              		4.3删除对应DOM元素
                        tar.parentNode.remove();
//                      4.5删除对应存储在本地的数据
                        that.changeData(function(i){
                        	 that.gm.splice(i,1);
                        });
                	
                    }
                }
		    }
  //          4.4通过点击获取的商品的id来找到本地存储中对应商品
            changeData(cb){
            // 根据点击的商品的id查找本地存储的数据中符合的商品数据
                for(var i=0;i<this.gm.length;i++){
                if(this.gm[i].goodsId === this.id){
                    cb(i);
                    break;
                }
                }
               // 剔除掉之后,得再存回去,否则仅仅是在内存中修改,没有修改本地存储
              localStorage.setItem("goodsMsg",JSON.stringify(this.gm));
            }
		
		
		}

这时我们可以检测一下是否已经达到了删除功能的效果:

购物车怎么设计 redis缓存_数组_05


当我们点击删除了最后一个商品时,这时对应商品已经从页面上去除了,

再让我们看一下本地存储

购物车怎么设计 redis缓存_购物车怎么设计 redis缓存_06


最后一个商品的数据跟随着我点了删除后,从本地存储中也删除掉了。

功能二:总价跟着数量进行改变

//5.总价跟着数量而改变
//              5.1首先也是通过事件委托拿到数量
                this.tBody.oninput = function(eve){
                	var e = eve || window.event;
                    var tar = e.target || e.srcElement;
                    if(tar.className === "number"){
                      //5.2.获取要修改数量的商品的id
                    that.id = tar.parentNode.parentNode.getAttribute("index");
                      // 5.3.执行修改本地存储中数据的功能
                    that.changeData(function(i){
                        that.gm[i].num = tar.value;
                    });
//                  5.4每次修改数量时,来计算总价
                    tar.parentNode.nextElementSibling.innerHTML = tar.value * tar.parentNode.previousElementSibling.innerHTML;
                    }
		        }
            }

下面我们来测试一下功能:

当我们通过改变数量时,总价跟随着本地存储中的数量一起改变了,实现了我们预想的功能。

这样一个初步的购物车就完成了,下面分享一下商城和购物车的总体代码,方便大家去测试和理解。

商城

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			.cont{width: 1000px;margin: 30px auto;border: 1px solid black;overflow: hidden;}
			.cont .goods{width:250px;float: left;border: 1px solid black;box-sizing: border-box;text-align: center;}
			.goods img{width: 80%;}
			.goods span{display: block;margin: 10px 0;}
			.goods p{height: 40px;line-height: 20px;overflow: hidden;}
			.goods input{display: block;margin: 0 auto;font-size: 20px;}
		</style>
	</head>
	<body>
		<h2>欢迎来到商城,请选购商品   <a href="购物车.html">点击进入购物车</a></h2>
		<div class="cont"></div>
	</body>
	<script type="text/javascript">
//		定义一个商品数组
		var data = [{
        img:"https://img12.360buyimg.com/n7/jfs/t1/94329/20/12711/106212/5e4a97bcE66a103ae/721ae0eaf9ecbaa7.jpg",
        price:"1999.00",
        name:"荣耀20S 李现同款 3200万人像超级夜景 4800万超广角AI三摄 麒麟810 全网通版6GB+128GB 蝶羽蓝",
        goodsId:"123asd"
    },{
        img:"https://img10.360buyimg.com/n7/jfs/t1/93499/17/90/221850/5da6d4ebE9747a490/8b167328e1dadff8.jpg",
        price:"2199.00",
        name:"【品质好物】5000mAh大电量,支持18W快充,Type-C充电接口!【K305G爆品开售,点击选购】",
        goodsId:"ajgjgj"
    },{
        img:"https://img12.360buyimg.com/n7/jfs/t1/103980/26/12527/248017/5e4a6b2bEde93b893/af9f1eb0617ce599.jpg",
        price:"2399.00",
        name:"这是一个手机,看着像手机就行,这是名字",
        goodsId:"12u3"
    },{
        img:"https://img10.360buyimg.com/n7/jfs/t11266/172/3136897597/311385/898550cb/5ce41430N7bb10f75.jpg",
        price:"1899.00",
        name:"这也是个手机,这是这个手机的名字",
        goodsId:"afa876"
    }];
    
    class GoodsList{
//  	1.构造函数
    	constructor(){
    		this.data = data;
    		this.cont = document.querySelector(".cont");
    	}
    	//  2.事件绑定
        init(){
//      	3.准备一个空字符串
    	  var str = "";
    	  for(var i = 0;i<this.data.length;i++){
//  	  	4.通过遍历商品数组,把商品属性添加到空数组中
    	  	str += `<div class="goods" index="${this.data[i].goodsId}">
                            <img src="${this.data[i].img}" alt="">
                            <span>${this.data[i].price}</span>
                            <p>${this.data[i].name}</p>
                            <input type="button" value="加入购物车" class="add">
                     </div>`
    	  }
//  	  5.把商品添加后在大框中显示
    	  this.cont.innerHTML = str;
        }
//      7.准备点击购买商品时,把数据本地储存
//      7.1因为事先大框中没有input元素,现在我们需要点击购买按钮,所以需要事件委托的方法
         addEvent(){
         	    var that = this;
         	    this.cont.onclick = function(eve){
         		var e = eve || window.event;
         		var tar = e.target ||e.srcElement;
//       		7.2判断如果选择到input元素,获取它的父元素的属性“index";
         		if(tar.className == "add"){
         			that.goodsId = tar.parentNode.getAttribute("index");
//              7.3开始进行本地存储数据
                 that.setData();
         		}
         	}
         }
         
//       8.本地存储数据
         setData(){
//       	8.1读取goodsMsgs数据
         	var gm = localStorage.getItem("goodsMsg");
//       	8.2判断本地是否有这个数据(数据所在的数组),没有那么就存储
            if(gm == null){
//          8.3没有就创建	
               gm = [{
               	goodsId:this.goodsId,
               	num:1,
               	msg:this.getData(this.goodsId)               	
               }]
            }
            else{
//          	8.4把数组json变成对象类型,方便直接获取属性
                gm = JSON.parse(gm);
                var zhuangtai = 0;
//              8.5判断存入的数据是否在数组中有,有的话加数量,没有的话把这个数据放到数组中
                for(var i = 0;i<gm.length;i++){
                	if(gm[i].goodsId == this.goodsId){
                		gm[i].num++;
                		zhuangtai = 1;
                		break;
                	}
                }
//             8.6 表示数组中没有此数据,添加进去
                if(zhuangtai == 0){
                	gm.push({
                		goodsId:this.goodsId,
                        num:1,
//                     8.7 通过传入的goodsid在getData()方法中,如果传入的数据=对应数据的id,那么就把对应的数据拿过来
                        msg:this.getData(this.goodsId)
                	})
                }
            }
            //9.以上这个if里面只是在判断操作获取到的数据,并没有存回去,所以最终操作完之后,需要将数据存到本地存储中
            localStorage.setItem("goodsMsg",JSON.stringify(gm));
         }
         
//      主要的作用是可以通过点击对应商品,获取商品id,然后遍历整个数据然后找到对应id所贮备的数据 
//        // 单独封装为了方便获取所有数据中,某个数据的功能
//       // 根据传入的id获取
         getData(id){
         	//遍历的时候,比较,符合,返回这个数据(判断是否有这个数据)
         	for(var i = 0;i<this.data.length;i++){
         		if(this.data[i].goodsId ==id){
         			return this.data[i];
         		}
         	}
         	//没有符合,返回空对象,保持数据格式一致
         	return {};
         }
//       
    }
//  6.可以先创建实例对象查看
    var gl = new GoodsList();
    gl.init();
    gl.addEvent();
    
	</script>
</html>

购物车

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			img{width: 100px;height: 100px;}
		</style>
	</head>
	<body>
		<h2>这是购物车   <a href="商城商品展示.html">点击返回商城</a></h2>
		<table border=1 width = 800px align = "center">
		<thead>
            <tr>
                <th>图片</th>
                <th>名字</th>
                <th>单价</th>
                <th>数量</th>
                <th>总价</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
        </tbody>	
		</table>
	</body>
	<script type="text/javascript">
		
		class Car{
//			1.构造函数
			constructor(){
				this.tBody = document.querySelector("tbody");
			}
//			2.从本地存储中拿到数据,准备在购物车页面显示
            getData(){
//          	2.1 立即拿到数据
                if(localStorage.getItem("goodsMsg")){
//              	2.2把其变为json对象格式,方便于调用其中的属性
                	this.gm = JSON.parse(localStorage.getItem("goodsMsg"));
                }
                else{
                	this.gm = [];
                }
                //3.准备渲染页面
                this.display();
            }
            display(){
//          	3.1 准备一个空字符串
            	var str = "";
//          	3.2把数据填入字符串中,准备放到页面上
            	for(var i=0;i<this.gm.length;i++){
                str += `<tr index="${this.gm[i].goodsId}">
                            <td><img src="${this.gm[i].msg.img}" alt=""></td>
                            <td>${this.gm[i].msg.name}</td>
                            <td>${this.gm[i].msg.price}</td>
                            <td><input type="number" min="1" value="${this.gm[i].num}" class="number"></td>
                            <td>${ this.gm[i].msg.price * this.gm[i].num }</td>
                            <td class="delete">删除</td>
                        </tr>`;
            }
//          	3.3渲染	
                this.tBody.innerHTML = str;
            }
//             事件绑定
            addEvent(){
               	var that = this;
//             4.删除功能
//             4.1因为我们一开始在html中并没有删除,所以需要用到事件委托
                this.tBody.onclick = function(eve){
                	var e = eve || window.event;
                	var tar = e.target || e.srcElement;
                	if(tar.className == "delete" ){
                		// 4.2先获取当前点击删除按钮的商品的id
                		that.id = tar.parentNode.getAttribute("index");
//              		4.3删除对应DOM元素
                        tar.parentNode.remove();
//                      4.5删除对应存储在本地的数据
                        that.changeData(function(i){
                        	 that.gm.splice(i,1);
                        });
                	
                    }
                }
//              5.总价跟着数量而改变
//              5.1首先也是通过事件委托拿到数量
                this.tBody.oninput = function(eve){
                	var e = eve || window.event;
                    var tar = e.target || e.srcElement;
                    if(tar.className === "number"){
                      //5.2.获取要修改数量的商品的id
                    that.id = tar.parentNode.parentNode.getAttribute("index");
                      // 5.3.执行修改本地存储中数据的功能
                    that.changeData(function(i){
                        that.gm[i].num = tar.value;
                    });
//                  5.4每次修改数量时,来计算总价
                    tar.parentNode.nextElementSibling.innerHTML = tar.value * tar.parentNode.previousElementSibling.innerHTML;
                    }
		        }
            }
  //          4.4通过点击获取的商品的id来找到本地存储中对应商品
            changeData(cb){
            // 根据点击的商品的id查找本地存储的数据中符合的商品数据
                for(var i=0;i<this.gm.length;i++){
                if(this.gm[i].goodsId === this.id){
                    cb(i);
                    break;
                }
                }
               // 剔除掉之后,得再存回去,否则仅仅是在内存中修改,没有修改本地存储
              localStorage.setItem("goodsMsg",JSON.stringify(this.gm));
            }
		
		
		}
//		4.先创建实例对象进行页面查看
		var c = new Car();
		c.getData();
		c.addEvent();
		
	</script>
</html>