Redux 之利用 distinct 属性进行性能优化
前言
在开启本篇的正文之前我们先做一个实验,我们来定义一个空的 Action
,也就是在 Reducer
中。这个 Action
什么也不做。然后我们在页面的Widget
的build
方法打印对应的信息在页面,通过响应按钮点击来调度这个 Action
。大家猜猜依赖于 Store
的组件是否会被重建(Rebuild
)?我们先看一下运行结果。
答案是:如果你什么都不做那就会重建。这肯定会让我们觉得奇怪,为什么状态数据没有改变,还是会做重建操作呢?
Redux 刷新机制
要回答上面的问题,我们就需要了解 Redux 的刷新机制,来看StoreConnector
源码中的定义:
Every time the store changes, the Widget will be rebuilt. As a performance optimization, the Widget can be rebuilt only when the [ViewModel] changes. In order for this to work correctly, you must implement [==] and [hashCode] for the [ViewModel], and set the [distinct] option to true when creating your StoreConnector.
英文看不懂,没关系,给你翻译翻译:
每次
Store
改变的时候,组件都会被重建。为了保证只有在ViewModel
改变的时候,组件才会被重建。为了让这种方式发挥作用,需要对ViewModel
实现[==]
和hashCode
方法,并且在StoreConnector
中设置distinct
属性为true
。
也就是我们为了在状态没改变的时候避免重建,需要做两个事情:
ViewModel
需要重载操作符==
方法和hashCode
方法,以根据这两个方法判断是否改变。设置
distinct
为true
。
第一项好理解,第二项则是因为在 Store 的定义中说的:
If set to true, the Store will not emit onChange events if the new State that is returned from your [reducer] in response to an Action is equal to the previous state. 如果设置为
true
,reducer
中针对一个Action
返回的状态和之前的状态相等的话,那么Store
不会发送onChange
事件。
减少刷新来优化性能
知道了上面两点,我们来对购物清单应用的代码做一下改造,首先是在 Store 定义的时候设置 distinct
为 true
。
之后对状态类 ShoppingListState
实现==
和 hashCode
方法。
其中==
操作符需要比对清单数据中的每一项是否都相等,只要有一项不相等,就返回 false
。这意味着我们的 ShoppingItem
也需要改造, 实现==
和 hashCode
方法。
好了,来看看效果,这个时候发现列表和底部的统计栏都没有再调用 build
方法了。
总结
对于全局的 Store
来说,如果使用不慎可能导致全局刷新,因此良好的习惯是设置Store
的 distinct
属性为 true
,并且重载状态对象的==
和 hashCode
方法,以减少不必要的刷新,优化性能。
版权声明: 本文为 InfoQ 作者【岛上码农】的原创文章。
原文链接:【http://xie.infoq.cn/article/9135a51904526295c1baa50ad】。文章转载请联系作者。
评论