React 类组件的生命周期

93 阅读4分钟

类组件的创建以及props和state

ES6方式的创建


import React from 'react'

import ReactDOM from 'react-dom'

class B extends React.Component{

constructor(props){

super(props)

}

render(){

return (

<div>hi</div>

)

}

}

export defalut B

但是需要注意的是,ES6的创建方式并不支持IE8等浏览器,可能需要用webpack+babel将其翻译成ES5即可。

有关props和state的内容可以看我的另外一篇博客

React组件入门

生命周期

什么是生命周期

类比如下代码:


let div = document.createElement('div')//这是div的create/construct过程

div.textContent = 'hi'//这是初始化state

document.body.appendChild(div)//这是div的mount的过程

div.textContent = 'hi2'//这是div的update过程

div.remove()//这是div的unmount的过程

React组件也有类似的过程,称之为生命周期

函数列表


constructor()

static getDerivedStateFromProps()

shouldComponentUpdate()

render()

getSnapshotBeforeUpdate()

componentDidMount()

componentDidUpdate()

componentWillUnmount()

static getDerivedStateFromError()

componentDidCatch()

其中比较重要的是

constructor()//在这里初始化state

shouldComponentUpdate()//return false阻止更新

render()//渲染,创建虚拟DOM

componentDidMount()//组件出现在页面

componentDidUpdate()//组件已更新

componentWillUnmount()//组件将移除

constructor

用途

初始化props

初始化state,但此时不能调用setState

用来写bind this如:


constructor(){

/*其他代码略*/

this.onClick = this.onClick.bind(this)

}

可以用新语法代替:


onClick = () =>{}

constructor(){/*其他代码省略*/}

也可以不写consturctor

shouldComponentUpdate

用途

返回true则表示不阻止UI更新

返回false则表示阻止UI更新

常见问题:shouldComponentUpdate有什么用

答:它允许我们手动判断是否进行组件更新,我们可以根据应用场景灵活地设置返回值,以免不必要的更新

示例:

image.png 如图中代码所示,点击事件触发后,n+1-1值是没有变化的,但是点击一次render触发一次。

image.png

但是加上shouldComponentUpdate后,如图

image.png

当新的state和就的state一致时,返回false取消更新,会发现无论怎么点击按钮,都只运行了一次render。

注意!shouldComponentUpdate(newProps,newState)的两个参数必须都要写,即使第一个不用,但是写来占位。

onClick时,n的值经过+1-1没有变化,但是生成了一个新的对象。新对象和旧对象的地址不同。

工作流程

没有shouldComponentUpdate(newProps,newState)时,更改数据后执行render生成新的虚拟DOM,与原来的对比进行局部的UI更新。但是加了shouldComponentUpdate(newProps,newState)后,发现数据没变,从render之前就截停了。节省了很多步骤。

收到它的启发,所有组件都可以用这种方式来进行优化,将newStatethis.state每个属性进行对比。

此外React内置了一个功能叫做React.PureComponent可以代替React.Component

image.png

代码主体不变,只是加了Pure即可实现刚才一样的效果。

**PureComponent 会在 render 之前对比新 state 和旧 state 的每一个 key,以及新 props 和旧 props 的每一个 key。

如果所有 key 的值全都一样,就不会 render;如果有任何一个 key 的值不同,就会 render。它是一个浅对比,指挥对比第一层的属性**

render

用途

展示视图

return(<div>...</div>)

只能有一个根元素

如果有两个根元素需要用<React.Fragment>包起来,可以简写为<></>

技巧
  • render里面可以写if-else

  • render里面可以写?:表达式

  • render里面不能直接写for循环,需要用数组

  • render里面可以写array.map(循环)

示例:

image.png

实现点击+1当n是偶数时显示n是偶数,当n是奇数时显示n是奇数

可以用问号冒号表达式

image.png

state中有数组时,可以用array.map()进行遍历


render() {

return this.state.array.map(n=><span>{n}</span>)

componentDidMount

用途

在元素插入页面后执行,这些代码依赖DOM

例如想要获取div的高度,可以在这个生命周期函数内写

发起加载数据的AJAX请求(官方推荐)

首次渲染会执行此钩子

示例:

image.png

此外还可以用ref,这样可以避免id冲突的问题

image.png

componentDidUpdate

用途

视图更新后执行代码

**也可以发起AJAX请求,用于更新数据

首次渲染不会执行此钩子

注意:在此处的setState可能会引起无限循环,除非在if里

若`shouldComponentUpdate``返回false则不会渲染

componentDidUpdate(preProps,preState,snapshot)

componentWillUnmount

用途

组件将要被移除页面然后被销毁时执行的代码

unmount过的组件不会被mount

原则:谁污染谁治理

举例:

假如在componentDidMount内监听了window.scroll

你就要在componentWillUnmount内取消监听

假如在componentDidMount里创建了Timer

你就要在componentWillUnmount里取消Timer