这是一个“购物车”添加、删除等功能的一个案例,我们先来看一下界面:

HTML:
- <div class="main">
- <div class="top">
- 商品名称:<input type="text" name="" value="" id="title" class="ipt" />
- 商品价格:<input type="text" name="" value="" id="price" class="ipt" />
- <input type="button" value="加入购物车" class="btn" id="addcart" />
- div>
- <div class="cart">
- <div class="tr">
- <div><input type="checkbox" name="" value="" id="selectAll" /> 全选按钮div>
- <div>商品名称div>
- <div>商品价格div>
- <div>数量div>
- <div>操作div>
- div>
-
- <div id="goods">div>
- div>
- <div class="footer">
- 总共<span id="count">0span>件商品,共计 <span id="amount">0span> 元
- <a href="javascript:;" class="r" id="delall">清空购物车a>
- div>
- div>
原先的goods结构:
- <div id="goods">
- <div class="tr" id="1655771835688">
- <div><input type="checkbox" name="ckboxs" value="1655771835688">div>
- <div>鼠标div>
- <div>100元div>
- <div>
- <a href="javascript:;" name="-">-a>
- <input type="text" value="1>
- div>
- <div><a href="javascript:;" name="del">删除a>div>
- div>
- div>
我们在JS中封装一个render()方法,主要目的是渲染数据到页面上,这样就不会是一个“死”数据、“死”结构。为了方法我们观察呢,我们可以先写一些假数据:
- //商品列表
- goods = [
- { id: 1, title: '手机', price: 100, num: 1,checked:true},
- { id: 2, title: '电脑', price: 1000, num: 1,checked:true},
- { id: 3, title: '鼠标', price: 10, num: 1,checked:false},
- ];
当我们通过render()方法动态获取结构和数据时,HTML中的goods以下的结构我们就可以不要了。
- //【方法】渲染数据到页面上
- render() {
- var str = '';
- // //循环所有的商品
- for(var i=0; i<this.goods.length; i++){
- }
-
- this.goodsNode.innerHTML = str
- }
其中,id、title、price、num以及单选框都不是固定的。铺垫已经做好了,我们来根据需求写相应的代码。
需要概述:当我们在“商品名称”和“商品价格”输入框中输入我们想要的商品与价格时,点击【加入购物车】按钮,我们的记录会被添加到商品列表中。
- //获取节点元素
- addCart = document.querySelector('#addcart')//添加事件按钮
-
- //监听事件
- addEvent() {
- var _this = this
- //添加数据
- this.addCart.addEventListener('click', function () {
- var title = document.querySelector('#title').value
- var price = document.querySelector("#price").value
- _this.addGoods({ title, price })
- })
- }
- //添加数据
- addGoods(obj) {
- //获取随机id
- obj.id = new Date().getTime() + Math.floor(Math.random() * 10).toString() + Math.floor(Math.random() * 10).toString() + Math.floor(Math.random() * 10).toString();
- obj.num = 1;
- obj.checked = false;
- this.goods.push(obj);
- //重新渲染数据
- this.render()
- }
我们先获取元素节点(addCart),然后注册监听事件。这里有两个点需要我们注意一下:
当我们点击“删除”按钮时,我们这一条数据都会被移除,我们先考虑一下,需要操作哪一个节点?我们要从数组中移除数据我们需要用到哪个API?

通过图片我们可以看到,“删除”标签与这一条数据的关系是:“删除”的父元素的父元素,所以我们可以获取"goods"这个节点,通过事件委派来实现;而数组删除数据,我们可以使用splice这个API。
-
- class Cart {
- goods = [
- { id: 1, title: '手机', price: 100, num: 1,checked:true},
- { id: 2, title: '电脑', price: 1000, num: 1,checked:true},
- { id: 3, title: '鼠标', price: 10, num: 1,checked:false},
- ];
- //获取元素
- goodsNode = document.querySelector('#goods')//商品列表DOM
- addCart = document.querySelector('#addcart')//添加事件按钮
-
- //监听事件
- addEvent() {
- var _this = this
- //注册删除事件
- this.goodsNode.addEventListener('click',function(e){
- if(e.target.name == 'del'){
- var id = e.target.parentNode.parentNode.id
- _this.delGoods(id)
- }
- })
- }
-
- //删除数据
- delGoods(id){
- for(var i=0; i<this.goods.length; i++){
- if(this.goods[i].id == id){
- this.goods.splice(i,1)
- }
- }
- this.render()
- }
-
- }
- var C1 = new Cart()
- C1.render()
- C1.addEvent()
- C1.delGoods()
-
页面中的单选框,我们单选框我们在单击时,我们看到的是单选框被勾上了或者没有被勾上,但是在我们的数据里,当我们没有选时,它的checked是否为false?就是我们在更改页面的checkbox时,是否能真正改变我们的数据呢。

这是我们没有写JS代码时的情况,数据并不会因为单选框是否被选上而改变,所以我们需要获取元素节点来操作数据。 因为和删除记录是同一个事件,所以我写在一起了。
-
- class Cart {
- goods = [
- { id: 1, title: '手机', price: 100, num: 1,checked:false},
- { id: 2, title: '电脑', price: 1000, num: 1,checked:true},
- { id: 3, title: '鼠标', price: 10, num: 1,checked:false},
- ];
- //获取元素
- goodsNode = document.querySelector('#goods')//商品列表DOM
- addCart = document.querySelector('#addcart')//添加事件按钮
- selectAll = document.querySelector('#selectAll')//全选
-
- //监听事件
- addEvent() {
- var _this = this
- //注册删除事件
- this.goodsNode.addEventListener('click',function(e){
- if(e.target.name == 'del'){
- var id = e.target.parentNode.parentNode.id
- _this.delGoods(id)
- }
-
- // 单击复选框
- if(e.target.name == 'ckboxs'){
- var id = e.target.parentNode.parentNode.id;
- _this.updateGoods(id,'checked',e.target.checked)
- }
- console.log(_this.goods)
- })
-
- //全选
- this.selectAll.addEventListener('click',function(){
- _this.selectAllGoods(this.checked)
- })
- }
-
- // 更新数据
- updateGoods(id,k,v){
- for(var i=0; i<this.goods.length;i++){
- if(this.goods[i].id == id){
- this.goods[i][k] = v
- }
- }
- this.render()
- console.log(this.goods)
- }
-
- //全选
- selectAllGoods(checked){
- for(var i=0;i<this.goods.length;i++){
- this.goods[i].checked = checked
- }
- this.render()
- }
- }
- var C1 = new Cart()
- C1.render()
- C1.addEvent()
- C1.delGoods()
- C1.updateGoods()
- C1.selectAllGoods()
-

可以看到,当我们点击单选框时,数据中相应的状态也得到了改变。
首先,我们要获取count、amount以及清空购物车等元素节点。
因为逻辑比较简单,我就直接把所有的代码放在这了,大家可以整体看一下!
- class Cart {
- goods = [
- { id: 1, title: '手机', price: 100, num: 1, checked: false },
- { id: 2, title: '电脑', price: 1000, num: 1, checked: true },
- { id: 3, title: '鼠标', price: 10, num: 1, checked: false },
- ];
- //获取元素
- goodsNode = document.querySelector('#goods')//商品列表DOM
- addCart = document.querySelector('#addcart')//添加事件按钮
- selectAll = document.querySelector('#selectAll')
- count = document.querySelector('#count')
- amount = document.querySelector('#amount')
- delall = document.querySelector('#delall')
-
-
- //监听事件
- addEvent() {
- var _this = this
- //监听事件
- this.addCart.addEventListener('click', function () {
- var title = document.querySelector('#title').value
- var price = document.querySelector("#price").value
- _this.addGoods({ title, price })
- })
-
- //注册删除事件
- this.goodsNode.addEventListener('click', function (e) {
- if (e.target.name == 'del') {
- var id = e.target.parentNode.parentNode.id
- _this.delGoods(id)
- }
-
- // 单击复选框
- if (e.target.name == 'ckboxs') {
- var id = e.target.parentNode.parentNode.id;
- _this.updateGoods(id, 'checked', e.target.checked)
- }
-
-
- // 减
- if (e.target.name == '-') {
- var id = e.target.parentNode.parentNode.id;
- _this.jian(id)
- }
- // 加
- if (e.target.name == '+') {
- var id = e.target.parentNode.parentNode.id;
- _this.jia(id)
- }
- })
-
- //全选
- this.selectAll.addEventListener('click', function () {
- _this.selectAllGoods(this.checked)
- })
-
- //清空购物车
- this.delall.addEventListener('click', function () {
- _this.goods = []
- _this.render()
- })
-
- }
- //添加数据
- addGoods(obj) {
- //获取随机id
- obj.id = new Date().getTime() + Math.floor(Math.random() * 10).toString() + Math.floor(Math.random() * 10).toString() + Math.floor(Math.random() * 10).toString();
- obj.num = 1;
- obj.checked = false;
- this.goods.push(obj);
- //重新渲染数据
- this.render()
- }
- //删除数据
- delGoods(id) {
- for (var i = 0; i < this.goods.length; i++) {
- if (this.goods[i].id == id) {
- this.goods.splice(i, 1)
- }
- }
- this.render()
- }
-
- // 更新数据
- updateGoods(id, k, v) {
- for (var i = 0; i < this.goods.length; i++) {
- if (this.goods[i].id == id) {
- this.goods[i][k] = v
- }
- }
- this.render()
- }
-
- //全选
- selectAllGoods(checked) {
- for (var i = 0; i < this.goods.length; i++) {
- this.goods[i].checked = checked
- }
- this.render()
- }
-
- // 数量减
- jian(id) {
- for (var i = 0; i < this.goods.length; i++) {
- if (this.goods[i].id == id) {
- if (this.goods[i].num > 0) {
- this.goods[i].num--
- } else {
- this.goods[i].num = 0
- }
- }
- }
- this.render()
- }
- // 数量加
- jia(id) {
- for (var i = 0; i < this.goods.length; i++) {
- if (this.goods[i].id == id) {
- this.goods[i].num++
- }
- this.render()
- }
- }
- //【方法】渲染数据到页面上
- render() {
- var str = '';
- // //循环所有的商品
- for (var i = 0; i < this.goods.length; i++) {
- }
-
- //价格
- var sum = 0;
- var n = 0;
- for (var i = 0; i < this.goods.length; i++) {
- if (this.goods[i].checked) {
- n += this.goods[i].num;
- sum += this.goods[i].num * this.goods[i].price
- }
- }
- this.amount.innerHTML = sum
- this.goodsNode.innerHTML = str
- this.count.innerHTML = n
- }
- }
- var C1 = new Cart()
- C1.render()
- C1.addEvent()
- C1.delGoods()
- C1.updateGoods()
- C1.selectAllGoods()
- C1.jian()
- C1.jia()
-