77. Class组件详解

Class

77. Class组件详解

英语小课堂

derived 导出的,衍生的,派生的

render渲染

super class 超类,父类

property属性

state状态

mount挂载

两种创建class组件的方式

ES5方式(过时)

import React from 'react'

const A = React.createClass({
  render(){
    return (
    	<div>hi</div>
    )
  }
})
export default A
//由于ES5不支持class,才会有这种方式

ES6方式

哪种好?

ES6的class方式好

以后我们只用这种方式创建类组件

浏览器不支持ES6怎么办

你公司怎么还在搞IE8,肯定是个破公司,跳槽吧

用webpack+babel将ES6翻译成ES5即可

props

外部数据

传入props给B组件

初始化

要么不初始化,即不写constructor

要么初始化,且必须写全套(不写super直接报错)

效果

这么做了之后,this.props就是外部数据对象的地址了

读取

读props会了,写props呢

不准写(入)props!!!永远不要尝试对props改写

改props的值(一个地址)

this.props = {/*另一个对象*/}

不要写这样的代码,没有意义

理由:既然是外部数据,就应该由外部更新

改props的属性

this.props.xxx = 'hi'

不要写这样的代码,没有意义

理由:既然是外部数据,就不应该从内部改值

原则

应该由数据的主人对数据进行更改

相关钩子

componentWillReceiveProps钩子

当组件接受新的props时,会触发此钩子

啥是钩子?黑话,你就将其翻译成“特殊函数”即可。

该钩子已经被弃用

更名为UNSAFE_componentWillReceiveProps

总而言之,不要使用这个钩子

方方为什么会教这个?不推荐使用为什么还要教?教是为了让你能看懂就代码,这钩子以前是推荐使用的。

Props的作用(面试可能会问)

  • 接受外部数据

只能读不能写

外部数据由父组件传递

  • 接受外部函数

在恰当的时机,调用该函数

该函数一般是父组件的函数

state

初始化State

读写State

读用this.state

this.state.xxx.yyy.zzz

写用this.setState(???,fn)

this.setState(newState,fn)

注意setState不会立刻改变this.state, 会在当前代码运行完后,再去更新this.state,从而触发UI更新

this.setState((state,props) => newState,fn)

这种方式的state反而更易于理解

fn会在写入成功后执行

写时会shallow merge

setState会自动将新state与旧state进行一级合并

生命周期

类比如下代码

同理

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

  • 可不写

生命周期之shouldComponentUpdate

用途

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

  • 返回false表示阻止UI更新

  • 示例见下页

面试常问

问:shouldComponentUpdate有什么用?

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

https://codesandbox.io/s/thirsty-meitner-zlg0v6?file=/src/App.js

启发:

其实可以将newState和this.state的每个属性都对比一下,如果全部相等,就不更新如果有一个不等,就更新

再启发:

为什么React不内置此功能?React确实内置了,这个功能叫做React.PureComponent,可以代替React.Component

如果面试官问PureComponent是干什么的?怎么回答?

答:PureComponent 会在 render 之前对比新 state 和旧 state 的每一个 key,以及新 props 和旧 props 的每一个 key。 如果所有 key 的值全都一样,就不会 render;如果有任何一个 key 的值不同,就会 render。

质疑:

为什么要用新的对象?为什么我们不直接在this.state身上改呢?

这触及到编程哲学了,以后聊

生命周期之render

用途

  • 展示视图 return (<div>...</div>)

  • 只能有一个根元素

  • 如果有两个根元素,就要用<React.Fragment>包起

  • <React.Fragment />可以缩写成<></>

技巧

  • render里面可以写if..else

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

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

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

所有的循环(array.map)都要加个key

生命周期之componentDidMount

组件已经挂载了。

用途

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

  • 比如你想获取div的高度,就最好在这里写

  • 此处可以发起加载数据的AJAX请求(官方推荐)

  • 首次渲染会执行此钩子

参数

看文档

生命周期之componentDidUpdate

用途

  • 在视图更新后执行代码

  • 此处也可以发起AJAX请求,用于更新数据(看文档)

  • 首次渲染不会执行此钩子

  • 在此处setState可能会引起无限循环,除非放在if里

  • 若shouldComponentUpdate返回false,则不触发此钩子

参数

看文档

生命周期之componentWillUnmount

用途

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

unmount过的组件不会再次mount

举例

如果你在componentDidMount里面监听了window scroll,那么你就要在componentWillUnmount里面取消监听。

如果你在componentDidMount里面创建了Timer,那么你就要在componentDidMount里面取消Timer。

如果你在componentDidMount里面创建了AJAX请求,那么你就要componentDidMount里面取消请求。

否则你就是菜逼

原则:谁污染谁治理

总结

分阶段看钩子执行顺序

https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

函数列表 - 必会

  • constructor() 在这里初始化state

  • shouldComponentUpdate() return false阻止更新

  • **render()**创建虚拟DOM

  • **componentDidMount()**组件已出现在页面

  • **componentDidUpdate()**组件已更新

  • **componentWillUnmount()**组件将死

不要忘了return true

希望你背下常用生命周期的拼写和用途

纠错:React.PureComponent

视频中说

PureComponent 会在 render 之前对比新 state 和旧 state 的每一个 key。

这句话错在不够完整,完整的说法是

PureComponent 会在 render 之前对比新 state 和旧 state 的每一个 key,以及新 props 和旧 props 的每一个 key。 如果所有 key 的值全都一样,就不会 render;如果有任何一个 key 的值不同,就会 render。

最后更新于

这有帮助吗?