先做数据,再做功能,最后界面
var goods = [
{
pic: './assets/g1.png',
title: '椰云拿铁',
desc: `1人份【年度重磅,一口吞云】
√原创椰云topping,绵密轻盈到飞起!
原创瑞幸椰云™工艺,使用椰浆代替常规奶盖
打造丰盈、绵密,如云朵般细腻奶沫体验
椰香清甜饱满,一口滑入口腔
【饮用建议】请注意不要用吸管,不要搅拌哦~`,
sellNumber: 200,
favorRate: 95,
price: 32,
},]
数据中缺少商品数量,两种做法
第一种:
给数组每一项去加上一个属性,好处是不用新开内存空间了
坏处是修改了原始数据
第二种:
新创建一个uiGoods对象,将原始数据当做参数传进去
UIGoods: {
data: goods,
choose: 0 //选择的商品数量
}
function createUIGoods (g) {
return {
data: g,
choose: 0
};
}
let uigoods = createUIGoods(goods[0]);
console.log(uigoods);
思考,我们现在需要创建对象,构造函数是专门用来创造对象的,所以用构造函数来做
function UIGoods (g) {
this.data = g;
this.choose = 0
}
let uig = new UIGoods(goods[0]);
console.log(uig);
NumberBox数字输入框,商品选中的问题
数量大于0,就显示减号和数量
数量等于0,只显示加号
商品总价应该怎么写?作为属性传递还是函数调用?
属性传递,会造成数据冗余
作为函数传递,会增加代码复杂性
是否选中
封装成es6的类
/**
*单件商品的数据
* @class UIGoods
*/
class UIGoods{
constructor(g) {
this.data = g;
this.choose = 2;
}
/**
*获取总价
* @return {*}
* @memberof UIGoods
*/
getTotalPrice () {
return this.data.price * this.choose;
}
/**
*是否选中此商品
* @return {*}
* @memberof UIGoods
*/
isChoose () {
return this.choose > 0;
}
}
let uig = new UIGoods(goods[0]);
console.log(uig);
商品数量的增减用函数做,考虑库存
如果需求有变动,库存可能只有10个,一直加超过库存如何处理?
整个界面的数据
把之前封装好的单个数据拿过来,添加配送门槛和配送费
class UIData {
constructor() {
const uiGoods = [];
for (let i = 0; i < goods.length; i++) {
let uig = new UIGoods(goods[i]);
uiGoods.push(uig);
}
this.uiGoods = uiGoods;
/* 配送门槛 */
this.deliveryThreshold = 30;
/* 配送费 */
this.deliveryPrice = 5;
console.log(uiGoods);
}
}
const ui = new UIData();
面向对象写法,计算商品总价
/**
* 增加某件商品的数量
* @param {*} index 下标
* @memberof UIData
*/
increase (index) {
this.uiGoods[index].increase();
}
/**
* 减少某件商品的选中数量
* @param {*} index 下标
* @memberof UIData
*/
decrease (index) {
this.uiGoods[index].decrease();
}
动态创建商品列表
两种方法
1、生成HTML字符串(parse HTML)
执行效率低,开发效率高
2、一个一个创建元素
执行效率高,开发效率低
这里用第一种
购物车动画
这样效率低,所以我们一开始就要监听动画,把普通函数变成箭头函数
抛物线动画
调用函数 ui.jump(0) ,会从第一件商品跳到购物车
目标坐标:购物车(位置不变)
起始坐标:商品加号(位置动态变化)
getBoundingClientRect(),获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。
购物车位置是不变的,所以不用每次调用都去计算他的坐标,一开始就可以算出来
抛物线 transition: cubic-bezier(贝塞尔曲线)
新生成一个加号的节点,结构是 div 包裹 i 标签
div横向移动,i 在 div 里纵向移动
cubic-bezier(x1,y1,x2,y2):定义一个时间曲线(贝塞尔曲线),可以为其配置四个参数,前两个参数为“ x1 ”和“ x2 ”,定义“开始控制点”,后两个参数为“ y1 ”和“ y2 ”,定义“结束控制点”
起始位置到目标位置,中间要添加reflow样式,否则动画不会生效,两种做法
1、改变或者重新计算几何信息,比如 div.clientWidth
2、requestAnimationFrame
事件委托,添加事件
利用冒泡原理,给goods-list注册事件去影响设置goods-item
判断样式,classList.contains() 判断它的类名有没有包含某一项
index = ${ i },利用自定义属性,实现点击加号时,NumberBox数量变化
elementNode.getAttribute(name):获取节点的属性,name是属性名称,比如ID,title,value等的值。