为什么要优化?
react
后期搭建项目,组件是非常之多的,会有很多的render和dom操作,如果不进行优化会造成页面卡顿,用户体验就不佳了。
在React中
如何避免不必要的render
(opens new window)中,我们了解到如何避免不必要的render
来应付上面的问题,主要手段是通过shouldComponentUpdate
、PureComponent
、React.memo
。
除此之外, 常见性能优化常见的手段有如下:
避免使用内联函数
使用 React Fragments 避免额外标记
使用 Immutable
懒加载组件
事件绑定方式
服务端渲染
如果我们使用内联函数,则每次调用render
函数时都会创建一个新的函数实例,如下:
import React from "react";
export default class InlineFunctionComponent extends React.Component {
render() {
return (
<div>
<h1>Welcome Guest</h1>
<input type="button" onClick={(e) => { this.setState({inputValue: e.target.value}) }} value="Click For Inline Function" />
</div>
)
}
}
我们应该在组件内部创建一个函数,并将事件绑定到该函数本身。这样每次调用 render
时就不会创建单独的函数实例,如下:
import React from "react";
export default class InlineFunctionComponent extends React.Component {
setNewStateData = (event) => {
this.setState({
inputValue: e.target.value
})
}
render() {
return (
<div>
<h1>Welcome Guest</h1>
<input type="button" onClick={this.setNewStateData} value="Click For Inline Function" />
</div>
)
}
}
用户创建新组件时,每个组件应具有单个父标签。父级不能有两个标签,所以顶部要有一个公共标签,所以我们经常在组件顶部添加额外标签div
这个额外标签除了充当父标签之外,并没有其他作用,这时候则可以使用fragement
其不会向组件引入任何额外标记,但它可以作为父级标签的作用,如下所示:
export default class NestedRoutingComponent extends React.Component {
render() {
return (
<>
<h1>This is the Header Component</h1>
<h2>Welcome To Demo Page</h2>
</>
)
}
}
在事件绑定
方式 (opens new window)中,我们了解到四种事件绑定的方式
从性能方面考虑,在render
方法中使用bind
和render
方法中使用箭头函数这两种形式在每次组件render
的时候都会生成新的方法实例,性能欠缺
而constructor
中bind
事件与定义阶段使用箭头函数绑定这两种形式只会生成一个方法实例,性能方面会有所改善
在理解Immutable
中 (opens new window),我们了解到使用 Immutable
可以给 React
应用带来性能的优化,主要体现在减少渲染的次数
在做react
性能优化的时候,为了避免重复渲染,我们会在shouldComponentUpdate()
中做对比,当返回true
执行render
方法
Immutable
通过is
方法则可以完成对比,而无需像一样通过深度比较的方式比较
从工程方面考虑,webpack
存在代码拆分能力,可以为应用创建多个包,并在运行时动态加载,减少初始包的大小
而在react
中使用到了Suspense
和lazy
组件实现代码拆分功能,基本使用如下:
const johanComponent = React.lazy(() => import(/* webpackChunkName: "johanComponent" */ './myAwesome.component'));
export const johanAsyncComponent = props => (
<React.Suspense fallback={<Spinner />}>
<johanComponent {...props} />
</React.Suspense>
);
采用服务端渲染端方式,可以使用户更快的看到渲染完成的页面
服务端渲染,需要起一个node
服务,可以使用express
、koa
(洋葱模型)等,调用react
的renderToString
方法,将根组件渲染成字符串,再输出到响应中
例如:
import { renderToString } from "react-dom/server";
import MyPage from "./MyPage";
app.get("/", (req, res) => {
res.write("My Page ");
res.write("");
res.write(renderToString(<MyPage/>));
res.write("");
res.end();
});
客户端使用render
方法来生成HTML
import ReactDOM from 'react-dom';
import MyPage from "./MyPage";
ReactDOM.render(<MyPage />, document.getElementById('app'));
通过上面初步学习,我们了解到react常见的性能优化可以分成三个层面: