77. Class组件详解
Class
77. Class组件详解
英语小课堂
derived 导出的,衍生的,派生的
render渲染
super class 超类,父类
property属性
state状态
mount挂载
两种创建class组件的方式
ES5方式(过时)
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有什么用?
答:它允许我们手动判断是否要进行组件更新,我们可以根据应用场景灵活地设置返回值,以避免不必要的更新
启发:
其实可以将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里面取消请求。
否则你就是菜逼
原则:谁污染谁治理
总结
分阶段看钩子执行顺序
函数列表 - 必会
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。
最后更新于
这有帮助吗?