其中标红的( componentWillMount、 componentWillReceiveProps、 componentWillUpdate )是 react 16.3 版本要移除的生命周期,移除缘由:react 打算在17版本中,添加 async rendering , react 将一个更新过程分为 render 先后两个阶段,render 前是能够被打断(好比有紧急任务),当生命周期被打断后,再次执行,并不会从断点继续执行,是从新执行的,因此这些生命周期就可能会运行屡次。html
同时为了弥补失去这三个生命,react 新增了两个生命周期: static getDerivedStateFromProps、 getSnapshotBeforeUpdatereact
getDerivedStateFromProps 会在调用 render 方法以前调用,而且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,若是返回 null 则不更新任何内容。算法
此方法适用于罕见的用例,即 state 的值在任什么时候候都取决于 props。编程
static getDerivedStateFromProps(nextProps, prevState) {
//根据nextProps和prevState计算出预期的状态改变,返回结果会被送给setState
//这是一个static,简单说应该是一个纯函数
}
复制代码
getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)以前调用。它使得组件能在发生更改以前从 DOM 中捕获一些信息(例如,滚动位置)。今生命周期的任何返回值将做为参数传递给 componentDidUpdate()。api
getSnapshotBeforeUpdate 返回的值会作为第三个参数传递给 componentDidUpdate。数组
getSnapshotBeforeUpdate(prevProps, prevState) {
...
return snapshot;
}
componentDidUpdate(prevProps, prevState, snapshot) {
}
复制代码
这是一个组件的子树。每一个节点中,SCU 表明 shouldComponentUpdate 返回的值,而 vDOMEq 表明返回的 React 元素是否相同。最后,圆圈的颜色表明了该组件是否须要更新。性能优化
react 父组件触发更新时,它的全部子组件都会触发更新(即便 props 和 state )并无改变,这样时候咱们在子组件中添加 shouldComponentUpdate 生命周期,判断状态是否变动,若是没有变动返回 false , 这个子组件就不会从新 render。bash
React.PureComponent 是 React 自动帮咱们在 shouldComponentUpdate 作了一层浅比较。app
if (this._compositeType === CompositeTypes.PureClass) {
shouldUpdate = !shallowEqual(prevProps, nextProps)
|| !shallowEqual(inst.state, nextState);
}
复制代码
React.memo 是一个高阶组件,相似于 React.PureComponent,不一样于 React.memo 是 function 组件,React.PureComponent 是 class 组件。dom
const MyComponent = React.memo(function MyComponent(props) {
/* 使用 props 渲染 */
});
复制代码
key 帮助 React 识别哪些元素改变了,好比被添加或删除。当子元素拥有 key 时,React 使用 key 来匹配原有树上的子元素以及最新树上的子元素。正确的使用 key 可使 react 的更新开销变小。
<ul>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
<ul>
<li key="2014">Connecticut</li>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
复制代码
概念:将公用方法包装成 Mixin 方法,而后注入各个组件,从而实现代码复用。( 已经不推荐 )
缺点:
概念:能够理解为组件工厂,传入原始组件,添加功能,返回新的组件。
缺点:
概念:Render Props 就是一个 render 函数做为 props 传递给了父组件,使得父组件知道如何渲染子组件。
优势:
缺点:
概念:hooks 遵循函数式编程的理念,主旨是在函数组件中引入类组件中的状态和生命周期,而且这些状态和生命周期函数也能够被抽离,实现复用的同时,减小函数组件的复杂性和易用性。
hooks api:
一个简单的 custom hooks:
import { useEffect } from 'react';
function useTitle(title){
useEffect(()=>{
document.title = title;
}, [title]);
}
复制代码
虚拟 Dom:react 将 Dom 抽象成一个对象树,经过对比新旧两个树的区别(diff 算法),而后将更新部分渲染出来。
diff 算法基于两个策略:
在 react 中,树的比对很是简单,react 只会对两棵树进行逐层比较,即比较处于同一层级的节点。
节点比较分红两种状况:(1)节点类型不一样,(2)节点类型相同,属性不一样。
状况(1):
// DOM Diff 操做
C.destroy();
D = new D();
A.append(D);
复制代码
状况(2):
//变动钱
<div style={{fontSize: '16px'}} ></div>
//变动后
<div style={{color: 'red'}} ><div/>
//执行操做
=> removeStyle fontSize
=> addStyle color 'red'
复制代码
当列表中插入 F 节点,以下图:
这个时候就会有两种状况:(1)节点没有表示惟一 key ,(2)节点表示了惟一 key
状况(1)结果以下图:
//执行过程
C unmount
D unmount
E unmount
F mount
C mount
D mount
E mount
复制代码
状况(2)结果以下图:
//执行过程
F mount
复制代码
若是在组件的渲染或生命周期方法中引起错误,整个组件结构就会从根节点中卸载,而不影响其余组件的渲染,能够利用 error boundaries 进行错误的优化处理。
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, info) {
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
复制代码
react 支持将组建挂在到其余 dom 节点,事件仍是按组件原有位置冒泡。
render() {
return ReactDOM.createPortal(
this.props.children,
domNode,
);
}
复制代码
Fiber 是对 react 核心算法 reconciliation 的更新实现,将本来的同步更新分红两个阶段。阶段1(Reconciliation Phase)的任务是片断化执行的,每一个片断执行完成以后,就会把控制权从新交给 react 调度模块,若是有更高优先级的任务就去处理,而低优先级更新任务所作的工做则会彻底做废,而后等待机会重头再来,若是没有就执行下一个片断。阶段2(Commit Phase)是同步执行的,reactDom 会根据阶段1计算出来的 effect-list 来更新 DOM 。
阶段1涉及的生命周期(可能会执行屡次):componentWillMount、 componentWillReceiveProps、 shouldComponentUpdate、 componentWillUpdate
阶段2涉及的生命周期:componentDidMount、 componentDidUpdate、 componentWillUnmount
全新的 Context API 能够很容易实现祖先节点和子节点通讯,而且没有反作用。
const ThemeContext = React.createContext('light');
class ThemeProvider extends React.Component {
state = {theme: 'light'};
render() {
return (
<ThemeContext.Provider value={this.state.theme}>
{this.props.children}
</ThemeContext.Provider>
);
}
}
class ThemedButton extends React.Component {
render() {
return (
<ThemeContext.Consumer>
{theme => <Button theme={theme} />}
</ThemeContext.Consumer>
);
}
}
复制代码
React.lazy() 提供了动态 import 组件的能力,实现代码分割。
Suspense 做用是在等待组件时 suspend(暂停)渲染,并显示加载标识。
import React, {lazy, Suspense} from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<Suspense fallback={<div>Loading...</div>}> <OtherComponent /> </Suspense>
);
}
复制代码