原文永久连接: https://github.com/AttemptWeb.....javascript
下面说到的React开发中注意的问题,部分是本身遇到过的点,部分是收集的,也算是React代码优化部分,此次作一个整理,但愿能够帮助到你html
当组件的props 或者 state 改变时,可能会出现重复setState的状况,对于重复的操做,咱们能够经过下面的方法来避免重复渲染:java
shouldComponentUpdate 返回true,确认真实DOM须要改变时,返回true。通常的作法是比较组件的props和state是否真的发生变化,若是发生变化则返回true,不然返回false。react
shouldComponentUpdate(nextProps, nextState) { if (this.props.id !== nextProps.id) { return true; } if (this.state.type !== nextState.type) { return true; } return false; }
React文档:shouldComponentUpdate()git
React文档:shouldComponentUpdate 的做用github
React.PureComponent,没必要写你本身的shouldComponentUpdate,它提供了一个浅比较。若是对象中包含复杂的数据结构,则有可能由于没法检查深层的差异,产生错误的比对结果。在你的 props 和 state 较为简单时,可使用 React.PureComponent。(补充:当你比较的目标为引用类型数据,浅比较会忽略属性或状态)api
class ChildComponent extends React.PureComponent { render() { return( <>{this.state.type}</> ) } }
不可变Immutable,Immutable Data 就是一旦建立,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操做都会返回一个新的 Immutable 对象。更多详情:Immutable 详解及 React 中实践数据结构
import { Map, is } from 'immutable'; constructor() { this.state = { // 建立 不可变Immutable data: Map({ times: 0 }) } } shouldComponentUpdate(nextProps, nextState) { for (const key in nextState) { // 经过 is 或者 !== 来比对 if (this.state[key] !== nextState[key] && !is(this.state[key], nextState[key])) { return true; } } } handleAdd() { // 一个全新的对象 const newData = this.state.data.update('times', v => v + 1); this.setState({ data: newData); }
不可变Immutable,目前我尚未在项目中尝试过,内容来源于社区,若是有相关文章,能够推荐给我。函数
key 帮助React识别哪些元素改变了,好比被添加或删除。所以你应当给数组中的每个元素赋予一个肯定的标识。对于列表组件,key 最好是这个元素在列表中拥有的一个独一无二的字符串。
listData.map((item) => <li key={item.id}> {item.text} </li> );
列表组件 Diff比对时,使用元素在数组中的下标做为 key,列表顺序发生修改,就表明原来的React节点组件没法复用,须建立新的React.Element节点,这样diff 会变得慢。
当基于下标的组件进行从新排序时,组件基于它们的 key 来决定是否更新以及复用,若是 key 是一个下标,那么修改顺序时会修改当前的 key,致使组件的 state(好比输入框)可能相互篡改致使没法预期的变更。
虚拟列表是常见的‘长列表'和'复杂组件树'优化方式,它优化的本质就是减小渲染的节点。只渲染当前视口可见元素。
虚拟列表适用场景:无限滚动列表, 表格,下拉列表,大数据量或无限嵌套的树等。
相关组件方案:
react-virtualized react-window
随着React的版本不断升级,函数式组件功能愈来愈强大,这也符合它的最初提倡的UI = fn(e)
。随着Hooks、memo的支持,函数组件已很是的成熟。
React.memo为高阶组件,可使用它替换现有的函数组件。它与 React.PureComponent 很是类似,但它适用于函数组件,但不适用于 class 组件。
function areEqual(prevProps, nextProps) { /* 若是把 nextProps 传入 render 方法的返回结果与 将 prevProps 传入 render 方法的返回结果一致则返回 true, 不然返回 false */ } function Component(props) { } React.memo(Component, areEqual)
第一个参数是函数组件,第二个参数非必须,主要是props的比较。默认状况下其只会对复杂对象作浅层对比,若是你想要控制对比过程,那么请将自定义的比较函数经过第二个参数传入来实现。
不管是 props和state 尽可能只传须要的数据,避免多余的更新。对于项目的后期维护特别重要。(我已经踩坑了。。。)
<ListInfoCard data={...state}>
列表组件、表单组件、商品卡片、icon组件,尽可能作到适度的拆分,业务组件和展现组件的分离,易于后期的维护和迭代,同时也能够提高性能。在平时开发中,对于一个单独的页面,数据量不大,直接将业务和展现组件捆绑在一块儿,在初期,这个是无关痛痒的,若是是一次性开发,问题也不是特别大,可是一旦去要后期的迭代优化,就有问题了。
本身遇到开发方面的问题基本就这些了,上面提到的基本都是我遇到过的和研究过的,但愿能够帮助到你。这些只是React项目代码层面的东西,若是你须要作一些优化方面的工做,也能够从打包、编译入手。
ps: 顺便推一下本身的我的公众号:Yopai,有兴趣的能够关注,每周不按期更新,分享能够增长世界的快乐