大家好,我是Kason。对于前端框架,长期以来一直存在各种争议。其中,争议最大的是以下两个:性能之争和API设计之争。例如,所有主要的新兴框架都会拿出基准来证明其出色的运行时性能。React通常在这些基准测试中垫底。在API设计方面,Vue爱好者认为:“更多的API约束了开发者,不会因为团队成员水平的不同而导致代码质量有较大差异。”而React粉丝认为:“Vue的大型API限制了灵活性,JSXyyds”。上面的讨论归结为框架性能和灵活性之间的权衡。本文将介绍一个名为legendapp的状态管理库,它在设计理念上与其他状态管理库有很大不同。在React中合理使用legendapp可以大大提高应用程序的运行时性能。但是这篇文章的目的不仅仅是介绍一个状态管理库,而是要和大家一起感受框架随着性能的提升在灵活性上的变化。欢迎加入人类优质前端框架群。React的性能优化不是很好已经是不争的事实。原因是React的自上而下的更新机制。每次状态更新时,React都会从根组件开始深度优先遍历整个组件树。既然遍历方式是固定的,那么如何优化性能呢?答案是找到遍历时可以跳过的子树。什么样的子树可以跳过遍历?显然没有改变的子树。在React中,变化主要是由以下三个元素引起的:statepropscontext,它们都可能改变UI,或者触发useEffect。因此,如果一个子树中的上述三个元素有变化,则可能发生变化,不能跳过遍历。我们从变化的角度来看一下React中的性能优化API。对于下面两个:useMemouseCallback,它们的本质都是为了减少props的变化。对于下面两个:PureComponentReact.memo,其实质是将props的比较方式从全等比较改为浅比较。状态管理库可以做的优化了解了React的性能优化之后,我们来看看状态管理库可以做哪些性能优化。性能瓶颈主要出现在更新的时候,所以性能优化主要有两个方向:减少不必要的更新和减少每次更新要遍历的子树,比如Redux上下文中的useSelector就是第一种方式。对于后一种路径,减少更新时遍历的子树通常意味着减少上面介绍的三个元素的变化。PS:黄轩开发的ReactForget是一个编译器,可以生成相当于useMemo和useCallback的代码。目的是为了减少三要素之间道具的变化。状态管理库在这方面能起到的作用非常有限,因为无论状态管理库封装得多么巧妙,都掩盖不了它操作的其实是一个React状态。例如,虽然Mobx为React带来了细粒度更新,但它并没有带来与Vue中细粒度更新匹配的性能,因为Mobx最终会触发自上而下的更新。legendapp的思路本文要介绍的legendapp也是走的第二条路,但是它的思路比较特别——如果减少3个元素的数量,那不就可以减少3个元素的变化吗?举个极端的例子,如果在一个庞大的应用中没有状态,更新时可以跳过整个组件树。以下是Hook实现的计数器示例。useInterval每秒触发一次回调,回调中触发更新:functionCounter(){const[count,setCount]=useState(1)useInterval(()=>{setCount(v=>v+1)},1000)return
