React性能优化:immutability-helper
项目地址:kolodny/immutability-helper
轮子作用:以最低的成本对抗浅比较。
适用场景:state的修改。
如果使用redux管理数据流,就必然会遇到state的修改。state修改有个特性,redux会进行一次新旧state的浅比较,如果有变动才会触发重新渲染。一个大的项目state的数据结构必然会很复杂,如果有一个很里层的数据被修改,这时就很头疼。
如果把state深拷贝一次会十分浪费资源,所以我们不会这么干。浅拷贝同样行不通,因为浅拷贝之后的操作会改变旧的state值,这既不规范,也不会触发渲染。
假如我们有如下一个state:
state = { info: { name: "tom", age: 12 }, score: { exam1: [99, 98, 89], exam2: [78, 85] } } 复制代码
进行一次浅拷贝copyState = state,此时的copyState与state其实保存了相同的值,他们指向内存中的同一片区域。如果现在我进行一番操作:
-
state.score.exam2.push(90);
-
复制代码
对于copyState与state而言,他们其实没有任何变化,依旧指向同一片内存区域,只是这片区域内保存的数据有了变化,所以此时两者仍然相等。
所以浅复制自然也就无法对抗浅比较,而且还可能出现意想不到的副作用(修改state导致copyState也变了)。
一个比较原始地方法就是把state照抄一遍,并进行所需的修改:
newState = {
info: state.info,
score: {
exam1: state.score.exam1,
exam2: [
state.score.exam2[0],
state.score.exam2[1],
90
],
},
}
复制代码
这就是最大程度上利用原有数据,在不深拷贝的情况下定向修改数据,并且返回一个新对象的操作。
但是上面的操作明显就很笨拙,在ES6引入了...操作符以后,这个操作就可以得到简化:
newState = {
...state,
score: {
...state.score,
exam2: [
...state.score.exam2,
90,
],
},
}
复制代码
但是可以想象,在数据层级比较深的时候就会写得很复杂,上面的...state.score.exam2已经是不短的一串代码了。
面对着这种困境,immutability-helper就是一个与使用...操作逻辑相同,但是书写要简便很多的轮子。这个轮子有一定的学习成本。上面的例子使用immutability-helper实现的具体操作如下:
import update from 'immutability-helper'; newState = update(state, { score: { exam2: { $push: [90] } } }) 复制代码
不难看出,用了immutability-helper以后少写了很多不必要的代码,immutability-helper实现的功能还不仅仅只是这些,有兴趣可以自行研究一下源码。它也是一个被antd推荐使用的轮子。
总而言之,十分推荐在React中使用immutability-helper来进行state的更新,兼具性能与优雅。

浙公网安备 33010602011771号