目标
1.能使用jQuery的方式生成所有手机的商品列表
2.能根据链接的id参数获取商品并在详情页展示
3.能使用localStorage把购物车商品列表数据存储越来
4.能从localStorage里面计算出购物车商品的数量并显示
5.能实现购物车数据在购物车页面的显示
6.能实现商品的数量加减功能
7.能实现购物车中勾选商品的总价计算
- 主要目标就是学习品优购的加入购物车流程
- 商品列表->商品查看->加入购物车->购物车结算
正常的流程应该是:美工给设计图->开始把设计图转化成为页面->把静态页面转移到自己的项目里面->开始实现功能
其实所有的商品数据,都应该是从服务器获取过来的,下个阶段要学习的ajax,就是去服务器获取数据的。但是我们没有这个条件,所以假装我们的数据就是从服务器来的。使用一个data.js模拟这些从服务器返回的数据
然后,在实际开发中,很可能需要我们自己根据项目的效果,先自己分析,需要一个怎样的数据结构。将来可能需要前端和后端并行开发,可能服务器还无法提供数据给前端,此时需要自己先模拟一些假的数据——需要构造数据结构的能力。
根据自己的列表页面,构造商品的数据结构
window.dataMock = [{
// 商品的id,用于区分每个商品的
"id": 1,
// 商品的图片的路径
"imgSrc": "./images/0a15aa6747a614b0.jpg",
// 商品的名字
"name": "小米 红米Redmi Note7 幻彩渐变AI双摄 4GB+64GB 梦幻蓝 全网通4G 双卡双待 水滴全面屏拍照游戏智能手机",
// 商品的价格
"price": 3366,
// 售出的百分比
"percent": 69,
// 商品剩余多少
"left": 1481
},
{},
{},
{}]
有了数据之后,我们只需要把数据显示在页面里面
直接把得到的数据数组,遍历,把每个对象,展示在页面中的每个商品里面就行
1.把该新建的页面新建好(list.js)
2.把所需的外部js引入list.html里面
<!-- 引入jq -->
<script src="./js/jquery-1.12.4.min.js"></script>
<!-- 引入模拟数据 -->
<script src="./js/dataMock.js"></script>
<!-- 引入当前页面的js -->
<script src="./js/list.js"></script>
3.遍历数组生成结构
let lis = dataMock.map(function (v, i) {
// 写生成结构的代码
});
我们需要把每个商品的数据进行动态的修改
return `<li class="goods-list-item">
<a href="detail.html?id=${v.id}">
<div class="item-img">
<img src="${v.imgSrc}" >
</div>
<div class="item-title">
${v.name}
</div>
<div class="item-price">
<span class="now">¥ ${v.price}</span>
</div>
<div class="sold">
<span> 已售 <em>${v.percent}% </em></span>
<div class="scroll">
<div class="per" style="width:${v.percent}%;"></div>
</div>
<span>剩余<i>${v.left}</i>件</span>
</div>
</a>
<a href="detail.html?id=${v.id}" class="buy">
查看详情
</a>
</li>`
拼接到页面
$(‘.goods-list > ul‘).html(lis.join(‘‘))
直接把商品的id,以浏览器地址栏额外数据的方式带过去
格式: 详情页面的地址.html?id=对应商品的id
只需要在生成结构的时候,把每个商品里面的a标签的跳转的地址,携带对应的id即可
<a href="detail.html?id=${e.id}">
根据地址栏里面的数据,得到商品的id,根据id获取对应的商品数据,把要替换的信息替换掉
1.新建一个该页面专用的js文件(detail.js)
2.在dedail.html里面引入三个js文件
<!-- 引入jq -->
<script src="./js/jquery-1.12.4.min.js"></script>
<!-- 引入模拟数据 -->
<script src="./js/dataMock.js"></script>
<!-- 引入当前页面的js -->
<script src="./js/detai.js"></script>
3.在detail.js里面获取id
//怎么获取跳转链接问号后面的id
//Location 对象存储在 Window 对象的 Location 属性中,表示那个窗口中当前显示的文档的 Web 地址
let id = location.search.split(‘=‘)[1]
// console.log(id)
3.1 防止直接打开页面
//如果不是从列表页跳转过来而是直接打开, 那么没有id, undefined
if (!id) {
// location.href = ‘../list.html‘ //错误
//JS文件内的相对路径,也是从HTML文件所在位置开始计算的,跟js文件在哪无关。
// CSS文件内如果写相对路径,是基于CSS文件本身的,跟谁引入了这个CSS无关。
// HTML代码中的相对路径就是以本HTML文件所在目录开始计算,无论引入的文件是js还是css还是图片还是其他任何类型。
location.href = ‘./list.html‘
}
4.遍历手机商品数组,筛选出对应的数据,修改页面上对应的数据
//遍历, 数组中满足id相同的, 取出来, 用filter
//filter返回符合条件的元素到新的数组中
let good = dataMock.filter(function (v) {
//为集合中的每个元素规定要运行的函数。如果返回 true,则保留元素,否则元素将被移除
return v.id == id
})[0]
//id是唯一的, 只要数组中的第一个
//console.log(good)
$(‘.preview-img > img‘).attr(‘src‘, good.imgSrc)
$(‘.sku-name‘).text(good.name)
$(‘.summary-price em‘).text(good.price)
需要把商品的数据存储到localStorage里面,这样就可以在购物车页面读取出来
需要把哪些数据存储到localStorage
商品的id
商品的图片
商品的名字
商品的数量
商品的单价
商品的选中状态 (只要有checked属性,就会被选中,所以用自定义的元素来存储选中状态)
本地存储的步骤
1. 获取本地存储 -- 字符串
2. 转成数组
3. 操作数组
4. 转成json
5. 存到本地存储
创建数据的格式
var good = {
id: 商品的id,
imgSrc : 商品的图片,
name : 商品的名字,
number : 商品的数量,
price : 商品的单价,
isChecked: true //默认勾选
}
1.点击加入购物车按钮
2.把以前的数据先读取出来
3.把新旧数据叠加
3.1如果旧数据里面已经有了当前这个商品,把数量叠加
3.2如果旧数据里面没有当前这个要添加的数据,把新数据push到数组里面
4.把新数据重新覆盖到localStorage里面
$(function () {
//一. 动态更改页面元素
//怎么获取跳转链接问号后面的id
//Location 对象存储在 Window 对象的 Location 属性中,表示那个窗口中当前显示的文档的 Web 地址
let id = location.search.split(‘=‘)[1]
// console.log(id)
//如果不是从列表页跳转过来而是直接打开, 那么没有id, undefined
if (!id) {
// location.href = ‘../list.html‘ //错误
//JS文件内的相对路径,也是从HTML文件所在位置开始计算的,跟js文件在哪无关。
// CSS文件内如果写相对路径,是基于CSS文件本身的,跟谁引入了这个CSS无关。
// HTML代码中的相对路径就是以本HTML文件所在目录开始计算,无论引入的文件是js还是css还是图片还是其他任何类型。
location.href = ‘./list.html‘
}
//遍历, 数组中满足id相同的, 取出来, 用filter
//filter返回符合条件的元素到新的数组中
let good = dataMock.filter(function (v) {
//为集合中的每个元素规定要运行的函数。如果返回 true,则保留元素,否则元素将被移除
return v.id == id
})[0]
//id是唯一的, 只要数组中的第一个
$(‘.preview-img > img‘).attr(‘src‘, good.imgSrc)
$(‘.sku-name‘).text(good.name)
$(‘.summary-price em‘).text(good.price)
//二. 点击按钮, 添加购物车数据到本地存储
$(‘.addshopcar‘).on(‘click‘, function () {
//1.获取本地存储
let dataArr = JSON.parse(localStorage.getItem(‘pyg_cart‘)) || []
//逻辑短路, 当本地存储没有pyg_cart, dataArr为undefined, 把一个空数组给它
// 3. 遍历dataArr, 如果id相同, 那么取出来, 增加数量. 如果id找不到即undefined, 往里面加新数据
let existGood = dataArr.filter(function (v) {
return v.id == id
})[0]
//数组和对象是引用传递, existGood的内存地址和dataArr中对应元素的内存地址是一样的
//在第一个加入购物车商品页面验证下:
console.log(existGood === dataArr[0]) //true
if (existGood) {
existGood.number += $(‘.choose-number‘).val() - 0
} else {
// 3.2.1获取当前页面购物信息
let newGood = {
id: good.id,
number: $(‘.choose-number‘).val() - 0, //$(‘.choose-number‘).val()是string
price: good.price,
name: good.name,
imgSrc: good.imgSrc,
isChecked: true
}
// 3.2.2 往数组里添加数据
dataArr.push(newGood)
}
//把数组添加到本地存储
localStorage.setItem(‘pyg_cart‘, JSON.stringify(dataArr))
})
})
需要处理一下购物车是否为空的情况
如果购物车是空的,就把空空如也显示,否则直接显示购物车数据
通过控制指定元素的类名来控制元素是否显示,因为的cart.css里面已经有了一个hidden的类名
判断购物车是否为空,如果为空,就把空空如也显示,把hidden加给其他的元素
// 判断购物车是否为空
var cartListData = localStorage.getItem(‘shopCart‘);
var arr = JSON.stringify(cartListData);
if(!arr){
arr = [];
}
// 如果我们处理过了数据,就是当数组的长度为0的时候,没有数据
if(arr.length !== 0){
// 有数据
// 把空空如也隐藏
$(‘.empty-tip‘).addClass(‘hidden‘);
}else {
// 没有数据
// 把表头和表格数据隐藏
$(‘.cart-header,.item-list‘).addClass(‘hidden‘);
}
接下来把数组里面的每个数据,加载到购物车里面,类似list.html里面一样,直接遍历数组,生成结构就行。
$(function () {
//1.获取本地存储
let dataArr = JSON.parse(localStorage.getItem(‘pyg_cart‘)) || []
let list = dataArr.map(function (v) {
return `<div class="item">
<div class="row">
<div class="cell col-1 row">
<div class="cell col-1">
<input type="checkbox" class="item-ck" checked="">
</div>
<div class="cell col-4">
<img src="${v.imgSrc}" >
</div>
</div>
<div class="cell col-4 row">
<div class="item-name">${v.name}</div>
</div>
<div class="cell col-1 tc lh70">
<span>¥</span>
<em class="price">${v.price}</em>
</div>
<div class="cell col-1 tc lh70">
<div class="item-count">
<a href="javascript:void(0);" class="reduce fl">-</a>
<input autocomplete="off" readonly="" type="text" class="number fl" value="${v.number}">
<a href="javascript:void(0);" class="add fl">+</a>
</div>
</div>
<div class="cell col-1 tc lh70">
<span>¥</span>
<em class="computed">${v.price * v.number}</em>
</div>
<div class="cell col-1">
<a href="javascript:void(0);" class="item-del">从购物车中移除</a>
</div>
</div>
</div>`
})
$(‘.item-list‘).html(list)
let totalNumber = 0
let totalPrice = 0
dataArr.forEach(item => {
totalNumber += item.number
totalPrice += item.number * item.price
});
$(‘.total-of .selected‘).text(totalNumber)
$(‘.total-money‘).text(totalPrice)
})
这个逻辑我们以前讲过了,快速实现
// 全选和单选功能
$(‘.pick-all‘).on(‘click‘,function(){
// 把其他的每一项都改成和我一样
var status = $(this).prop(‘checked‘);
// 获取每个商品的checkbox
$(‘.item-ck‘).prop(‘checked‘,status);
});
单选功能
// 需要使用委托的方式注册
$(".item-list").on(‘click‘,‘.item-ck‘,function(){
var cks = $(‘.item-list .item-ck:checked‘);
var ck = $(‘.item-list .item-ck‘);
var flag = cks.length === ck.length;
$(‘.pick-all‘).prop(‘checked‘,flag);
});
1.先点击,注册点击事件,需要使用委托的方式实现
2.获取点击的商品对应的id,根据id到localStorage里面把对应的数据删除
3.把对应的商品的结构删除
1.获取元素,注册事件,但是是动态生成的,需要使用委托的方式实现
2.点击加号的时候,获取当前是多少件,从输入框里面获取,需要把value进行数字的转换,之后+1
减号同理
3.要把加减的结果保存到localStorage里面
3.1要根据点击的加减按钮,得到对应的商品的id,去本地存储里面,找到对应的额数据,进行number的修改
3.2重新覆盖
从localStorage里面读取数组的过程是一样的,所以可以直接封装好了,使用
/**
* @description 读取存储在localStorage里面的数组的
* @param {string} key 存储数据使用的键
* @return {Array} 返回一个数组,如果不存在,返回空数组
*/
function loadData(key){
var str = localStorage.getItem(key);
var arr = JSON.parse(str);
if(!arr){
arr = [];
}
return arr;
}
解决平时字符串不能换行书写的问题。
语法:ES6 新增的语法。
var str = `反引号内部可换行,可敲空格,都可识别`;
反引号内部挖坑: - 拼接变量数据
var str = ` ${变量名} `;
反引号处理字符串,${} 挖坑填充替换数据。
设置本地存储 - 如果本地没有数据,就是添加,如果有就是修改数据的值。
localStorage.setItem("键名称", 数据);
键名称需要写成字符串格式。
坑:数据在保存到本地存储的时候,会自动转换成字符串进行存储。
获取本地存储
var 返回值 = localStorage.getItem("键名称");
坑:返回成功的数据绝对是字符串的格式,查找失败返回 null。
本地存储是永久性的,除非你把数据清除掉了。
JSON 主要用于前后端数据的传输。
JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。
JSON 对比之前的 JS 对象区别:
JSON 格式更加严格。
我们一般不会重新改写数据,JS 提供了方法进行转换。
JSON.stringify(对象)
JSON.parse(对象)
浏览器的地址是可以携带一定的数据信息的,格式
网址?键=值&键=值&键=值....
例如:
https://www.baidu.com/s?wd=%E7%8B%97%E8%9B%8B&rsv_spt=1&rsv_iqid=0x897f6a80000038c7
只需要得到问号后面的部分就可以知道一些上一个页面传递过来的信息,通过location对象可以获取,location对象有一个属性:location.search,这个属性是专门管理页面的跳转地址的数据的
console.log(locatin.search);
[ ] 数组,每个商品的关键信息就是数组的每一项
{ } 对象,对象中用键值对的形式存储了商品的数据
[] 数组 获取值,一般用到遍历全部,如果想到拿到单项就用 [索引值]。
{} 对象 获取值,通过 点语法获取值。
原文:https://www.cnblogs.com/jiutianzhiyu/p/13971537.html