react性能上的一点点思考

最近在react上做一个orderBook深度图,数据接入用websocket,数据形式是第一次请求返回当前orderBook,之后每当数据有更新便会收到某个priceLevel的最新数据,大概频率是每秒30个。

做深度图的策略就是2个series的steped Area Chart,两个series以当前价格为中心,分别代表买卖单。获取到第一组完整数据之后将数据格式化(dataArray)、排序并依次相加获得该priceLevel的总容量=>计算出当前价格(最高买入价格和最低卖出价格的中位数)=>计算出当前要显示的数据范围=>渲染.

最终效果如下
depthChart

数据是real-time的,每接收到一个新的数据,更新我们的dataArray(删除、修改、新增),重新排序和加和、计算最新价格并触发渲染。

按照这样的思路做完之后,由于数据更新频率过快,数据量较大(30000+条),频繁重新渲染chart导致卡顿甚至卡死。
所以做出以下优化:

  • state更新将触发页面重新渲染,我们可能需要管理很多状态,但并不是所有状态都需要用setSate来保存,setState只存放必要的需要触发页面重绘的状态,以减少不必要的渲染
  • 数据更新改为每0.5秒更新一次,setState每0.5秒执行一次
  • 优化Array的增删改

setState

setState不是同步的,但也不能严格说他是异步的。setSate执行后不会立即更新这个state而是放入一个队列中,React.js内部会把JavaScript事件循环中的消息队列的同一个消息中的setState都进行合并以后再重新渲染组件。
但是我们也可以通过使用回调函数实现state的同步更新。
同时要注意setState不会判断新的state是否真的发生了变化,也就是说如果我设置了相同的state值,页面同样会进行渲染,如果项目中可能会有大量类似的情况,可以用shouldComponentUpdate这个生命周期钩子避免。shouldComponentUpdate接受两个参数:nextPropsnextState

1
2
3
4
5
6
7
8
//在render函数调用前判断:如果前后state中Number不变,
通过return false阻止render调用

shouldComponentUpdate(nextProps,nextState){
if(nextState.Number == this.state.Number){
return false
}
}

关于使用这个生命周期钩子的弊端,不详做讨论==>http://www.infoq.com/cn/news/2016/07/react-shouldComponentUpdate

Array的增删改

  • 删除最后一个元素:pop

  • 删除开头元素: shift

  • 要删除指定元素: splice(i,1)–删除i开始1个元素,从i开始之后每一个元素都需要往前挪一个位置

  • 依据条件删除多个元素: filter

  • 末尾添加一个元素:push(elm)

  • 开头添加一个元素: unshift

  • 添加元素到指定位置: splice(i,0,elm)–i位置开始删除0个元素,在该位置添加elm

  • 若需要更高效率的增删元素的话,建议使用linkList

  • 数组的原生sort排序方法是没有规定内部使用什么排序算法的,不同的浏览器内核有不同的实现,chrome,ie:快排, firfox:归并。
    应根据项目情况选择使用原生排序还是自行封装

定时器

react定时器要在componentDidMount生命周期方法挂上,然后在componentWillUnmount生命周期方法清除。

1
2
3
4
5
6
7
componentDidMount() {
this.interval = setInterval(() => this.func(), 1000);
}

componentWillUnmount() {
clearInterval(this.interval);
}

react life cycle