Yapei Li

专注于前端领域

0%

React16组件生命周期

挂载阶段的组件生命周期

把 React.js 将组件渲染,并且构造 DOM 元素然后塞入页面的过程称为组件的挂载 这是一个从无到有的过程

React.js 控制组件在页面上挂载和删除过程里面几个方法:

  1. componentWillMount:组件挂载开始之前,也就是在组件调用 render 方法之前调用。

    17 版本会被抛弃,避免在此方法中引入任何 side-effects(例如,数据获取或动画) 或 subscriptions(订阅)。 对于这些用例,请改用componentDidMount()。

    建议使用 constructor() 来代替初始化状态

  2. componentDidMount:组件挂载完成以后,也就是 DOM 元素已经插入页面后调用。

  3. componentWillUnmount:组件对应的 DOM 元素从页面中删除之前调用。

1
2
3
4
5
6
7
8
9
-> constructor(props)             //实例化(构造)组件
-> componentWillMount() // 组件挂载开始之前
-> render() //渲染组件的内容
// 然后构造 DOM 元素插入页面
-> componentDidMount() //组件挂载完成以后
// ...
// 即将从页面中删除
-> componentWillUnmount() //删除之前
// 从页面中删除

在组件的 render 之前调用 componentWillMount

在 DOM 元素塞入页面以后调用 componentDidMount

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//header组件   打印各个生命周期
class Header extends Component {
constructor () {
super()
console.log('construct')
}

componentWillMount () {
console.log('component will mount')
}

componentDidMount () {
console.log('component did mount')
}

componentWillUnmount() {
console.log('component will unmount')
}

render () {
console.log('render')
return (
<div>
<h1 className='title'>React 小书</h1>
</div>
)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//控制header组件显示隐藏 的组件
class Index extends Component {
constructor() {
super()
this.state = {
isShowHeader: true
}
}

handleShowOrHide () {
this.setState({
isShowHeader: !this.state.isShowHeader
})
}

render () {
return (
<div>
{this.state.isShowHeader ? <Header /> : null}
<button onClick={this.handleShowOrHide.bind(this)}>
显示或者隐藏标题
</button>
</div>
)
}
}

ReactDOM.render(
<Index />,
document.getElementById('root')
)

打印结果:
Alt text

一些组件启动的动作,包括像 Ajax 数据的拉取操作、一些定时器的启动等,可以放在 componentWillMount 里面进行

更新阶段的组件生命周期

setState 导致 React.js 重新渲染组件并且把组件的变化应用到 DOM 元素上的过程,这是一个组件的变化过程

  1. shouldComponentUpdate(nextProps, nextState):你可以通过这个方法控制组件是否重新渲染。如果返回 false 组件就不会重新渲染。这个生命周期在 React.js 性能优化上非常有用。

    比较 this.props 与 nextProps 以及 this.state 与 nextState,并返回 false 告诉 React 可以跳过这次更新

  2. componentWillReceiveProps(nextProps):组件从父组件接收到新的 props 之前调用。

    使用此生命周期方法通常会导致错误和不一致,因此将来会被弃用。

    如果您=需要 执行一个 side effect(例如,数据获取或动画)以响应 属性(props) 的更改,请改用componentDidUpdate 生命周期方法代替

  3. componentWillUpdate():组件开始重新渲染之前调用。

    17版本会被移除

    在更新发生之前调用

    在第一次渲染时不会被调用

    这里不能调用 this.setState()或者委派一个 Redux 动作

    此方法可以使用 componentDidUpdate() 代替

    如果正在使用此方法读取 DOM(例如,保存滚动位置),使用 getSnapshotBeforeUpdate()替代

  4. componentDidUpdate(prevProps, prevState, snapshot):组件重新渲染并且把更改变更到真实的 DOM 以后调用。

不常用生命周期

static getDerivedStateFromProps(props, state)

在调用 render 方法之前被调用,包括初始装载(mount)和后续更新时。 它应该返回一个更新 state(状态) 的对象,或者返回 null 以不更新任何 state(状态)。

可以替代componentWillReceiveProps 监听props变化

1
2
3
4
5
6
7
class App extends React.Component {
...
static getDerivedStateFromProps(props, state){

}
...
}

getSnapshotBeforeUpdate(prevProps, prevState)

在最近一次的渲染输出被提交之前调用。它使您的组件能够在DOM发生潜在变化之前捕获一些信息(例如滚动位置)。此生命周期返回的任何值将作为参数传递给componentDidUpdate()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class ScrollingList extends React.Component {
constructor(props) {
super(props);
this.listRef = React.createRef();
}
//返回的结果 传递给componentDidUpdate
getSnapshotBeforeUpdate(prevProps, prevState) {
//前一个props 与 当前props作比较(当前props已更新)
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
//接收getSnapshotBeforeUpdate返回的结果 作为第三个参数
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}

render() {
return (
<div ref={this.listRef}>{/* ...contents... */}</div>
);
}
}