该图是要完成的渲染样式,其中红色框 1、2、3是本次思考点。
首先,这个页面和之前写过的大部分相同,都是将数据对象写在同一个数组中,然后通过数组解构+对象解构的方式,获取每一个数据,并添加标签等进行页面渲染。那么我们来分析一下差异点。首先是1和2模块的差异是相同的,并不是每一个对象都有“赠品”,2模块中的数据也不尽相同,有“大小”、“颜色”、“数量”;然后是3模块,很明显出现了数字,而且是上下有关联的数据。
那么我们先来想想解决方法,首先我们很快想到在获取数据的时候,就可以判断“赠品”与2模块的数据的存在与否,这是第一次我的写法
const goodsList = [
{
id: '4001172',
name: '称心如意手摇咖啡磨豆机咖啡豆研磨机',
price: 289.9,
picture: 'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',
count: 2,
spec: { color: '白色' }
},
{
id: '4001009',
name: '竹制干泡茶盘正方形沥水茶台品茶盘',
price: 109.8,
picture: 'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',
count: 3,
spec: { size: '40cm*40cm', color: '黑色' }
},
{
id: '4001874',
name: '古法温酒汝瓷酒具套装白酒杯莲花温酒器',
price: 488,
picture: 'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',
count: 1,
spec: { color: '青色', sum: '一大四小' }
},
{
id: '4001649',
name: '大师监制龙泉青瓷茶叶罐',
price: 139,
picture: 'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',
count: 1,
spec: { size: '小号', color: '紫色' },
gift: '50g茶叶,清洗球'
}
]
let counts = []
document.querySelector('.list').innerHTML = goodsList.map(e => {
const { id, name, price, picture, count, spec: { size, color }, gift } = e
// console.log(id, name, price, picture, count, size, color, gift);
counts.push(price * count)
let newGift = ''
let spec = `<p class="spec">${color}/${size}</p>`
if (typeof (gift) !== 'undefined') {
newGift = gift.split(',').map(e => `<span class="tag">【赠品】${e}</span>`).join(' ')
}
if (typeof (size) === 'undefined') {
spec = ` <p class="spec">${color}</p>`
}
return `
<div class="item">
<img src='${picture}' alt="">
<p class="name">${name} ${newGift}</p>
${spec}
<p class="price">${price}</p>
<p class="count">${count}</p>
<p class="sub-total">${price * count}</p>
</div>`
}).join(' ')
document.querySelector('.total span').innerHTML = counts.reduce((pre, next) => {
return pre + next
}).toFixed(2)
很明显存在不足的是:1.我直接获取spec对象的大小和颜色(不管有还是没有),然后再去判断大小是否存在,这样产生的不足有:代码冗长,并且只能渲染大小和颜色,万一后续出现其他的属性,或者不只需要渲染一个,那么就不好维护。2.赠品模块,我也是直接获取再去判断是否存在,也有代码冗长的问题。3.数字处理不到位,单价这里数字没有保留小数,不美观,并且计算时没有考虑精度问题,数据可能会发生错误 + 把一部分总计的数字处理放在了渲染页面里面,代码非常乱,大大降低了代码的可读性。
以下是改进后的代码:
const goodsList = [
{
id: '4001172',
name: '称心如意手摇咖啡磨豆机咖啡豆研磨机',
price: 289.9,
picture: 'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',
count: 2,
spec: { color: '白色' }
},
{
id: '4001009',
name: '竹制干泡茶盘正方形沥水茶台品茶盘',
price: 109.8,
picture: 'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',
count: 3,
spec: { size: '40cm*40cm', color: '黑色' }
},
{
id: '4001874',
name: '古法温酒汝瓷酒具套装白酒杯莲花温酒器',
price: 488,
picture: 'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',
count: 1,
spec: { color: '青色', sum: '一大四小' }
},
{
id: '4001649',
name: '大师监制龙泉青瓷茶叶罐',
price: 139,
picture: 'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',
count: 1,
spec: { size: '小号', color: '紫色' },
gift: '50g茶叶,清洗球'
}
]
let counts = []
// 1.渲染页面
document.querySelector('.list').innerHTML = goodsList.map(e => {
const { id, name, price, picture, count, spec, gift } = e
// console.log(id, name, price, picture, count, size, color, gift);
// 规格文字模块处理
const text = Object.values(spec).map(e => e).join('/')
// console.log(text);
// 赠品模块
const str = gift ? gift.split(',').map(e => `<span class="tag">【赠品】${e}</span>`).join(' ') : ''
// 计算小计
const subTotal = ((price * 100 * count) / 100).toFixed(2)
return `
<div class="item">
<img src='${picture}' alt="">
<p class="name">${name} ${str}
<p class="spec">${text}</p></p>
<p class="price">${price.toFixed(2)}</p>
<p class="count">${count}</p>
<p class="sub-total">${subTotal}</p>
</div>`
}).join(' ')
document.querySelector('.total span').innerHTML = counts.reduce((pre, next) => {
return pre + next
}, 0).toFixed(2)
// 2.合计模块
const total = goodsList.reduce((prev, next) => (prev + (next.price * 100 * next.count) / 100), 0)
document.querySelector('.amount').innerHTML = total.toFixed(2)
可以看到,1.在spec这里,我获取的是spec整个对象,然后再利用Object.values()方法获取里面的键对值,直接渲染了spec盒子里面的文字,这意味着不管spec对象里面有多少个键值对,我都可以直接把它转换成文字,完美解决了只能渲染大小和颜色的问题。2.赠品这里我用了一个条件表达式,使代码更简洁。3.数字处理这里,一是先将数据 * 100,计算完以后再 / 100,解决了小数精度问题,也在单价那加上了保留两位小数,二是把总计数字处理的代码全部放到合计模块,增加了代码的可读性。