文章目录
公司业务需求,需要做一个活动页面,页面中会展示大约1万多个商品.
这就对页面的加载性能很有要求和技巧了.
页面中大概有小分类100个.


页面刚做完时,加载时间在5~7秒的样子.
初始版本
代码如下:
constructor (props) {
this.state = {
type2: [],
type3: [],
type4: [],
type5: [],
...
type108: []
}
}
componentDidMount () {
this.getGoodList()
}
getGoodList () {
this.setState({
type2: goodList.type2,
type3: goodList.type3,
...
type108: goodList.type108,
})
}
这里面的getGoodList()
方法耗时巨大,所以接下来需要对其进行改造
优化版本
改造思路:
页面直接加载全部数据–>页面展示具体某个分类时,加载该分类的商品数据
代码如下:
增加判断dom元素是否在浏览器可视范围的函数
checkVisibleInDocument = (node) => {
if (!(node.offsetHeight || node.offsetWidth
|| node.getClientRects().length)) {
return false
}
// 获取元素的高度和元素顶部相对视口的距离
const { height, top } = node.getBoundingClientRect()
const windowHeight = window.innerHeight || document.documentElement.clientHeight
// 只需要确定元素顶部相对视口左上角的垂直距离小于视口的高度且元素底部相对视口左上角的垂直距离
// 大于0
return (top < windowHeight) && (top + height > 0)
}
在加载商品列表的方法中加入函数判定
getGoodList () {
for (let i = 2; i <= 108; i++) {
if (this.checkVisibleInDocument(document.getElementById('' + i))) {
switch (i) {
case 2:if(this.state.type2.length == 0) {this.setState({ type2: goodList.type2 })}break;
case 3:if(this.state.type3.length == 0) {this.setState({ type3: goodList.type3 })}break;
...
default:
break
}
}
}
增加滑屏事件监听
componentDidMount () {
window.addEventListener('scroll', this.handleScroll)
}
handleScroll = (e) => {
let ctx=this;
let clientHeight = document.documentElement.clientHeight; //可视区域高度
let scrollHeight =document.documentElement.scrollHeight
if(clientHeight != scrollHeight) {
ctx.getGoodList()
}
}
这样一来,用户刚进入页面时,只会加载第一个分类的数据,而在滑动时再一一加载其他分类的数据
此时页面响应速度已经来到了1秒以内.
解决锚点跳转时的滑屏问题
但由于页面中存在带有锚点的导航条,在点击跳转时,会同时触发滑屏事件,这回导致在快速定位到指定位置时,会加载若干个分类的数据,这和我们的期望不符
解决方式如下:
在锚点组件中增加onCLick事件
<Anchor affix={false} onClick={this.getSolimg}>
...
</Anchor>
在事件中先移除滑屏事件监听,在0.5秒后再还原
getSolimg = () => {
window.removeEventListener('scroll', this.handleScroll)
setTimeout(()=>{
this.handleScroll();
window.addEventListener('scroll', this.handleScroll);
}, 500);
}
PS: 在这个页面中,一开始还使用了
Zmage
组件,但由于数据量过大,会出现数据未加载完毕时,图片都显示组件加载中
的状态