仓库地址:Dragact手感丝滑的拖拽布局组件
预览地址:支持手机端噢~
上回我们说到,Dragact组件已经进行了一系列的性能优化,然而面对大量数据的时候,依旧比较吃力,让我们来看看,优化之前的Dragact。
纵向堆叠着314个方块,插入时明显的卡顿,大约1秒的延迟
同样纵向堆叠着314个方块,插入时卡顿明显减少很多,可以接受
在实际生产过程中,可能不会有那么多物块,就拿我们项目的dashboard来说,整个屏幕最多只有10个方块,就已经是了不起了。
但是强迫症犯了,为了使得性能达到极致,再次进行了深度的优化。
React优化的策略有哪些呢?
策略一: shouldComponentUpdate()
因为React 的diff只是简单的深度优先+刷新策略去diff html tag,所以数据的改变,React是不会知道的。
因此,开发者必须得自己去diff数据,shouldComponentUpdate就是用来diff数据的一个特殊声明周期函数。
具体的,请看我之前的回答和徐飞叔的回答:
方正:Vue为什么没有shouldComponentUpdate的生命周期?
徐飞:Vue为什么没有shouldComponentUpdate的生命周期?
策略二:用记忆功能函数去缓存大量计算结果
有很多情况下,我们的遍历是不可避免的。
React中最著名性能问题,就是selector问题,现在大家也都知道用reselect去做性能优化了,但是本质呢?
我们写一点伪代码来做演示:
//首先,我们有一个斐波那契生成函数 fib(); //用户想用的时候,就会去掉这个函数 const number = fib(); //我们知道,fib()函数里面会经过大量的计算,才得出我们想要的结果 //但是,除了第一次计算之外,之后的所有计算都是不需要的,因为我们已经在一开始拿到结果了 //怎么做最好呢?闭包; const Fib = function (){ var cache = void 666; return function(){ if(!cache){ cache = fib(); return cache; } return cache; } }();
//当用户调用Fib的时候,只会在第一次进行计算,之后的后只会从cache中拿出来。
不要小看这种优化,很多时候,我们大量重复的遍历就会导致性能的低下。
策略三:减少dom的深度
我们都知道,每次react 更新的时候,都会进行diff,深度越大,diff的层次越多。
减少diff的层次是非常重要的性能优化手段,尤其是数据量巨大的时候。
具体怎么去减少dom的深度,方法有很多,我用的方法是:render children的办法。
简单的举个例子,拖拽组件:
<Dragger> <div>我是拖拽的组件</div> </Dragger>
这样的一个设计,看似很简单,很明了。用Dragger组件去包囊我们想要的组件,就可以让其获得拖拽的属性。
这么做不是不行,但是很多时候我们在设计之初,没考虑那么多,就会使用这样一种方式去设计:
class Dragger extends Component{ moving(){}...... render(){ return (<div onMouseDown={...} onTouchDown={...} style={....} > {this.props.children} </div>) } }
是不是很常见?这么做的问题其实很明显,就是无缘无故的,我们多了一层div,组件一多,那么就多会了几层div,无疑造成了渲染压力。
使用render children,我们可以这么设计
class Dragger extends Component{ moving(){}...... render(){ const provided = { onMouseDown:this.onMouseDown onTouchDown:this.onTouchDown style:{....} } return this.props.children(provided); } }
在外部使用的时候,就变成了:
<Dragger> {(provided)=><div {...provided}>我是拖拽的组件</div>} </Dragger>
看似稍微蛋疼了一些,但是好处就是:减少了dom的层级。
还有更多好处,可以看之前的一篇文章:React组件:拖拽布局Dragact v0.1.6 发布
手感的优化
看似很标准,实际上用户需要拖动很远,才会物体进行交换
看似很标准,实际上用户需要拖动很远,才会物体进行交换,造成这样让人不适的感觉原因是因为计算时,我取的计算中心永远是物体的顶边。
所以,当物体向下滑动的时候,必须要物体的顶边到达下一个物块的中心才能发生交换。
上图我们可以看到,长条的物块,已经拖出了屏幕很远,才会进行交换。
就这一点点差异,让我顿时感到不爽!
为了使得手感更加优异,做了大量实验以后,我发现,把移动中心设置在物体的重力中心,最为舒适。
把移动中心设置在物体的重力中心,最为舒适。
这一点点设计的改变,使得手感完全不同了。
你可以狠狠的点击:预览地址
到此,Dragact组件,无论从性能,还是手感上来说,都已经相当的符合我们的需求了。
yeah~
各位,我们下次见。