背景:有赞微商城后台商品管理页,底部增长供货商品推荐资源位,根据不一样的商家展现不一样的商品!前端
做为深耕的业务,咱们就从一个我遇到的复杂需求开始作个引子。栗子以下(可先看图片过个眼瘾):node
基本要求:react
更高要求:程序员
size
小于等于 goodList.length
则不予以 ajax
请求数据,减小没必要要的带宽size
获取不一样的数据,以及分页当你们看到产品的 PRD ,看了这个需求和要求以后,每一个人根据本身的程序开发经验和设计经验上,每一个人都能给出不一样的解决方案。其实呢,每一个解决方案都是一种方式,只是在不一样的角度上实施以及设计的思惟上不一样。So,我想分享给你们的,也是通过个人思考后以及完善的一种解决方案,拿出来仅供参考。ajax
分享实施方案前,先讨论一下到底什么是业务;而程序员写代码都是服务于业务的么? 在老板眼中,业务就是赚钱的工具;在销售员眼中,业务就是必须完成的指标;在产品的眼中,业务就是须要实现完成的需求。。。每一个人对业务的理解都不同,可是,有谁考虑过,在前端开发工程师眼中的业务究竟是什么??后端
下面是我站在前端的角度去理解业务,以下:浏览器
So,在个人理解里,前端所写的业务拆分红为6大部分:缓存
在简单的业务需求中,可能我拿到的后端数据,就直接能够渲染视图层,而后就完善功能。从开发的成本和复杂度考量上,是不值得去作业务拆分。因此,在复杂的业务需求中以及兼顾拆分和维护中,这种业务方法论就能够大展手脚了。如下就是我拿开头的例子,详细解析围绕业务的 6 大部分的设计。性能优化
结构划分:本次组件划分的规则是先上下、再左右、由外至内;划分结果是工具
BackHeader
GoodsList
GoodsCard
功能划分: 顶级容器:错误隔离,灰度控制,埋点数据及控制,ajax 请求。 视图展现:分发数据,组件回调
:::info 提示:由react16
提供 componentDidCatch
进行错误隔离,也可使用 try...catch
实现错误隔离 :::
在 react
中,最核心、也就最灵活的处理视图变化的方式呢,就将驱动视图的数据作成可配的;因此第一步,根据结构的划分,将需求作成数据的配置,代码以下:
render() {
const { goodsList, pageIndex, size } = this.state;
if (!goodsList.length) {
return <div ref={node => this.fenxiaoRef = node} />;
}
return (
<div className="fenxiao-recommend " ref={node => this.fenxiaoRef = node}>
<BlockHeader onGoodsChange={this.handlerClick} />
<GoodsListContainer size={size} pageIndex={pageIndex} goodsList={goodsList} />
</div>
);
}
复制代码
顶级容器组件在 DidMount
时,作灰度控制,ajax
获取数据驱动视图。BlockHeader
接收 props onGoodsChange
回调,请求数据,再分发数据。
计算当前可展现的商品数量 size
;获取顶层容器 ref
获取容器获取容器宽度。代码以下:
/** * 计算展现多少卡片 * 返回值 * size */
computedStyle = () => {
const { fenxiaoRef } = this;
if (!fenxiaoRef) {
return;
}
const { width } = fenxiaoRef.getBoundingClientRect();
let size = Math.floor(width / 144);
this.setState({ size });
}
复制代码
根据 size
获取商品的个数 goodsList
,并监听 window resize
;其中如下集中状况则不予以请求
size <= goodsList.length
时;size
埋点数据:曝光 曝光埋点的基本需求是,当商品出如今浏览器的视口中后(即用户的视口),发送黄金令箭!曝光一个商品发送一支令箭!
那么问题来了,如何判断当前分销商品列表广告位(分销商品 DOM 元素)出如今用户的视口呢?
我采用了一种比较 low
,也是最常规的解决方案:以浏览器视口左下角为原点坐标,向上为正,向下为负; 获取当前 DOM
距离页面顶部的距离,即 const { top } = node.getBoundingClientRect()
,获取视口高度 document.ocumentElement.clientHeight
;
// 以页面右下角为原点,计算分销商品是否 曝光
export function isExposure(node) {
if (!node) {
return null;
}
// 视口高度
const clientHeight = ddcocument.documentElement.clientHeight;
const { top } = node.getBoundingClientRect();
return clientHeight > top;
}
复制代码
“小公司写代码,大公司改代码”好多年前就据说过这么一句话,可是做为程序猿来讲,最大的痛点就是:别人不写文档,别人不写注释,以及写文档,写注释!因此在原有系统的维护当中,尽最大可能作到: