JS用面向对象的思想实现的购物车
首先先了解面向对象的编写思想。
有面向过程的编程和面向对象的编程。
面向过程:举一个经典例子:把大象放进冰箱里。
首先第一个过程是先打开冰箱,2.然后就是把大象放进去。3.再最后一个过程就是把冰箱关上。这就是面向过程编程的思想。
面向对象的思想:首先先想这些有哪些对象:1.有冰箱、大象。
然后对于冰箱这个对象它有哪些功能呢:1.打开冰箱门。3.把大象放入。2.关闭冰箱门。
了解了这2个思想后,怎么用面向对象的思想实现购物车呢?
首先:搞清楚购物车有哪些对象,只有商品这一个对象。它有哪些属性,有哪些功能。
看效果图
增加、删除、减少、全选、取消全选功能都有。
html部分
然后JS部分
var goods = [
{
id: 1,
name: "Apple iPhone 12 Pro Max (A2412) 128GB 海蓝色 支持移动联通电信5G 双卡双待手机",
img_url: "http://img12.360buyimg.com/n1/s450x450_jfs/t1/122505/19/15070/68848/5f861494Ebe330db5/24bc162f493ec940.jpg",
price: 9299.00,
count: 1
},
{
id: 2,
name: "华为 HUAWEI P40 Pro+ 麒麟990 5G SoC芯片 5000万超感知徕卡五摄 100倍双目变焦 8GB+256GB陶瓷黑全网通5G",
img_url: "http://img10.360buyimg.com/n1/s450x450_jfs/t1/112286/14/8665/320732/5ed23081E43dffed4/2a542499846ace02.jpg",
price: 7988.00,
count: 1
},
{
id: 3,
name: "华为 HUAWEI Mate 40 Pro麒麟9000 5G SoC芯片 超感知徕卡电影影像 66W有线超级快充8GB+256GB亮黑色5G全网通套餐二",
img_url: "http://img13.360buyimg.com/n1/s450x450_jfs/t1/136340/2/13085/73504/5f917f5cE8f24c5d6/87140d08acee9bf5.jpg",
price: 6999.00,
count: 1
},
{
id: 4,
name: "小米11 Ultra 至尊 5G 骁龙888 2K AMOLED四曲面柔性屏 陶瓷工艺 12GB+256GB 黑色 游戏手机",
img_url: "http://img13.360buyimg.com/cms/jfs/t1/174632/21/1005/122003/6061b875E54afeca8/e32b75af9e4da505.jpg",
price: 6499.00,
count: 1
},
{
id: 5,
name: "索尼(SONY)Xperia1 II 5G智能手机 4K屏 骁龙865 12G+256G 微单技术 蔡司镀膜 拍照游戏 20帧/秒 夜砚黑",
img_url: "http://img14.360buyimg.com/n1/s450x450_jfs/t1/151857/40/2398/38943/5f8842b9Edac7df98/0a8a77bfea24aa1d.jpg",
price: 7499.00,
count: 1
}
]
class Car {
constructor(goods, ul) {
this.goods = goods;
this.check_goods = [];
this.element = document.getElementById(ul);
this.init();//调用初始化函数。
this.addEvent()
}
//初始化函数
init() {
let str = "";
for (let i = 0; i < this.goods.length; i++) {
str += `<li index="${this.goods[i].id}">
<div class="check">√</div>
<img src="${this.goods[i].img_url}"alt="">
<p class="good_id">商品编号:${this.goods[i].id}</p>
<p class="good_name">${this.goods[i].name}</p>
<span class="price">价格:¥${this.goods[i].price}</span>
<div class="add_del">
<span>数量:</span>
<button class="reduce">-</button>
<span class="count">${this.goods[i].count}</span>
<button class="add">+</button>
</div>
<button class="del">移除</button>
</li>`
}
this.element.innerHTML += str;
};
//更新用于保存数据的this.goods
goods_updata(index, num) {//接收2个参数,第一个是商品id,第二个是count某一个商品数量(第二个可以不用传。)
for (let i = 0; i < this.goods.length; i++) {
if (this.goods[i].id == index) {//循环找到要改变的商品,然后进行改变其中的数据。
if (num) {
this.goods[i].count = num;
}
else {
index = Number(index) - 1
this.goods.splice(index, 1)
}
}
}
};
//事件委托,给最外面的ul添加点击事件
addEvent() {
let ul = document.getElementById("ul");
let that = this;
ul.onclick = function (ev) {//当点击ul中的某一个标签的时候,同时传递一个参数ev。
let e = ev || window.event;
let tar = e.target//e中有一个target属性,这时候的tar就是ul下你点击的标签。
switch (tar.className) {//根据tar的点击的标签类名和下面的case进行匹配,然后触发对应的函数。
case "reduce":
that.reduce(that, tar)//同时把参数传过去。
break;
case "add":
that.add(that, tar)
break;
case "del":
that.del(that, tar)
break;
case "check":
that.check(that, tar);
break;
case "checked":
that.checked(that, tar)
break;
case "all":
that.all(tar)
break;
case "notall":
that.notall(tar)
}
}
};
//减少商品数量的函数
reduce(that, tar) {
let id = Number(tar.parentNode.parentNode.getAttribute("index"))//每一个商品就是一个li标签,同时设置了有个index属性,index就是商品的id。
let count = tar.nextElementSibling;//获取到减少按钮的下一个兄弟节点(显示商品数量的标签)
if (count.innerHTML == 1) {//判断数量是否等于1。
count.innerHTML = 1//等于1就然他就等于1,不能再减少了
}
else {//否则就把商品数量进行减一
count.innerHTML = Number(count.innerHTML) - 1
}
that.goods_updata(id, Number(count.innerHTML));//调用之前数据更新的那个函数,同时把id(就是index)和修改后的count值传给该函数。
this.sum_price()//调用商品价格求和函数,求选中商品的价格。
};
//添加商品数量的函数
add(that, tar) {
let id = Number(tar.parentNode.parentNode.getAttribute("index"))//同时先获取到你点击的li标签的index属性,商品的id。
let count = tar.previousElementSibling;//获取到增加按钮的上一个兄弟节点。也就是显示数量的标签。
count.innerHTML = Number(count.innerHTML) + 1;//增加数量就不需要判断,就直接增加数量。
that.goods_updata(id, Number(count.innerHTML))//调用数据更新函数。
this.sum_price()//求选中商品的价格
}
//移除商品
del(that, tar) {
let id = Number(tar.parentNode.getAttribute("index"))//一样先来获取点击的商品的id
tar.parentNode.remove();//这里就是移除li标签,就是把商品移除。
that.goods_updata(id);//然后更新数据,把id传过去。
this.checked(this, tar)//这里:如果商品选中了,再点击移除按钮的话,就先调用取消选中函数(checked),这样才能保住总价格的动态显示
this.sum_price()//求和选中商品
}
//选中商品给圆圈添加样式,然后用一个数组来存选中后的商品。
check(that, tar) {
let li = tar.parentNode;
li.setAttribute("class", "liactive")//改变标签的类名(class),因为前面的是通过类名class来判断执行哪个函数的。
tar.setAttribute("class", "checked");
let check_id = Number(tar.parentNode.getAttribute("index"));//获取商品id
for (let i = 0; i < that.goods.length; i++) {
if (that.goods[i].id == check_id) {//通过id判断商品
that.check_goods.push(that.goods[i]);//用一个空数组把选中的商品保存进空数组。(因为求商品的函数求和就直接读取该数组就行了)
}
}
this.sum_price()
}
//当在点击的话就取消红色样式,取消选中。
checked(that, tar) {
//判断是否为全部选中,如果全部选中,就把全部选中按钮进行更改。
if (this.check_goods.length == this.goods.length) {
let all = document.getElementById("all")
all.innerHTML = "选中全部"
all.setAttribute("class", "all");
}
let li = tar.parentNode;
li.setAttribute("class", "")
tar.setAttribute("class", "check")
let check_id = Number(tar.parentNode.getAttribute("index"));
for (let i = 0; i < that.check_goods.length; i++) {
if (that.check_goods[i].id == check_id) {//通过id判断选中商品数组中是不是有id这个商品有就删去
that.check_goods.splice(i, 1)//把取消的商品从保存选中商品的数组中删去。
}
}
this.sum_price()
}
//选中商品价格求和
sum_price() {
let total_price = 0
for (let i = 0; i < this.check_goods.length; i++) {
total_price += this.check_goods[i].count * this.check_goods[i].price;
}
let total = document.getElementById("total_price");
total.innerHTML = `总价格:¥${total_price}`
}
//选中全部商品的按钮。
all(tar) {
tar.innerHTML = "取消全部"
tar.setAttribute("class", "notall")
let li = document.querySelectorAll("li");
let check = document.querySelectorAll(".check")
for (let i = 0; i < li.length; i++) {
li[i].setAttribute("class", "liactive")
}
for (let i = 0; i < check.length; i++) {
check[i].setAttribute("class", "checked")
}
//把现在最新的商品的数据赋值给保存选中商品的数组中
this.check_goods = [...this.goods]
this.sum_price()
}
//取消全部选中
notall(tar) {
tar.innerHTML = "选中全部";
tar.setAttribute("class", "all");
let li = document.querySelectorAll("li");
let check = document.querySelectorAll(".checked")
for (let i = 0; i < li.length; i++) {
li[i].setAttribute("class", "")
}
for (let i = 0; i < check.length; i++) {
if (check[i].getAttribute("class") == check) {
tar.innerHTML = "选中全部"
}
check[i].setAttribute("class", "check")
}
this.check_goods = [];
this.sum_price()
}
}
//调用类Car,同时传参数(商品数量,最外层的ul类名)
let car = new Car(goods, "ul");