使用immutable优化React
React在减少重复渲染方面确实是有一套独特的处理办法,那就是虚拟DOM,但显然在首次渲染的时候React绝无可能超越原生的速度,或者一定能将其它的框架比下去。尤其是在优化前的React,每次数据变动都会执行render,大大影响了性能,特别是在移动端。 React 默认的渲染行为初始化渲染在初始化渲染时,我们需要渲染整个应用 提出改变我们想更新一部分数据。这些改变只和一个叶子节点相关(绿色的)
理想更新我们只想渲染通向叶子节点的关键路径上的这几个节点(绿色的) 默认行为如果你不告诉 React 别这样做,它便会如此
从上图可以看见,组件除了必要渲染的三个节点外,还渲染了其他不必要渲染的节点,这对性能是一个很大的浪费。如果对于复杂的页面,这将导致页面的整体体验效果非常差。因此要提高组件的性能,就应该想尽一切方法减少不必要的渲染。 React的生命周期React的生命周期如下,还没熟悉的同学可以去熟悉一下。 shouldComponentUpdate因为其中的 React性能优化的关键在于 在上面的示例中,因为 C2 的 C1 和 C3 的 React.PureComponent在传入组件的props和state只有一层时,我们可以直接使用 React.PureComponent,它会自动帮我们进行浅比较(shallow-compare),从而控制shouldComponentUpdate的返回值。 但是,当传入props或state不止一层,或者未array和object时,浅比较( ImmutableJavaScript 中的对象一般是可变的(Mutable),因为使用了引用赋值,新的对象简单的引用了原始对象,改变新的对象将影响到原始对象。如 foo={a: 1}; bar=foo; bar.a=2 你会发现此时 foo.a 也被改成了 2。虽然这样做可以节约内存,但当应用复杂后,这就造成了非常大的隐患,Mutable 带来的优点变得得不偿失。为了解决这个问题,一般的做法是使用 而Immutable 可以很好地解决这些问题。 什么是Immutable Data
可以看看下面这个经典的动画:
immutable.jsImmutable.js本质上是一个JavaScript的持久化数据结构的库 ,但是由于同期的React太火,并且和React在性能优化方面天衣无缝的配合,导致大家常常把它们两者绑定在一起。 Immutable.js是Facebook 工程师 Lee Byron 花费 3 年时间打造,但没有被默认放到 React 工具集里(React 提供了简化的 Helper)。它内部实现了一套完整的 其中有 3 种最重要的数据结构说明一下:(Java 程序员应该最熟悉了)
简单示例 import { Map } from "immutable"; const map1 = Map({ a: 1,b: 2,c: 3 }); const map2 = map1.set('b',50); map1.get('b'); // 2 map2.get('b'); // 50 seamless-immutableseamless-immutable是另一套持久化数据结构的库,它并没有实现完整的 简单示例 // 使用 seamless-immutable.js 后 import Immutable from 'seamless-immutable'; var array = Immutable(["totally","immutable",{hammer: "Can’t Touch This"}]); array[1] = "I'm going to mutate you!" array[1] // "immutable" array[2].hammer = "hm,surely I can mutate this nested object..." array[2].hammer // "Can’t Touch This" for (var index in array) { console.log(array[index]); } // "totally" // "immutable" // { hammer: 'Can’t Touch This' } JSON.stringify(array) // '["totally",{"hammer":"Can’t Touch This"}]' seamless-immutable的实现依赖于ECMAScript 5 的一些特性,如Object.defineProperty 和 Object.freeze,因此会在浏览器兼容性方面有所欠缺:
不过这不是问题啦,可以使用 polyfill es-shims/es5-shim 来解决。 对比虽然 Immutable 中的 Map 和 List 虽对应原生 Object 和 Array,但操作非常不同,比如你要用 当使用外部库的时候,一般需要使用原生对象,也很容易忘记转换。 当然也有一些办法来避免类似问题发生:
但是还有一个致命的问题是,对现有代码的改造,使用 Immutable.js 成本实在太大。 而 React中使用由于seamless-immutable的实现依赖于ECMAScript 5 和原生的Array、Object天然的兼容性,导致其在React中的使用非常简单,只要注意三点就可以达到效果: 初始化state初始化state数据的时候,使用Immutable的初始化方式。 import Immutable from 'seamless-immutable'; state: { orderList: Immutable([]),} 修改state数据修改state数据的时候,同样也要注意: saveOrderList(state,{payload: items}) { return {...state,orderList: Immutable(items)}; } shouldComponentUpdate使用pure-render-decorator,真是方便、快捷又优雅。当然,由于decorator属于ES7的特性,babel还需要自己配置。 import React from 'react'; import pureRender from 'pure-render-decorator'; @pureRender class OrderListView extends React.Component { render() { const {orderList} = this.props; return ( <div> { orderList.map((item) => { return ( <div key={item.orderNum}> <div>{item.orderNum}</div> <div>{item.createTime}</div> <div>{item.contact}</div> <hr/> </div> ); }) } </div> ); } } export default OrderListView; 怎么样,传说中的React的SCU的优化就是这么简单,赶紧去试试吧。 参考
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |