class 生命周期
常用以及必须掌握的声明周期
-
constructor() // 初始化state
-
**shouldComponentUpdate() // return true 不阻止更新 / return false 阻止更新
** -
render() // 创建虚拟DOM
-
****componentDidMount () // 组件已经出现在页面上
-
******componentDidUpdate() // 组件已经更新
-
********componentWillUnmount() // 组件即将销毁
简单的执行顺序
首次渲染 : constructor -- render -- 更新UI -- componentDidMount
再次渲染(更新数据):props/setState()改变了 -- shouldComponentUpdate -- 是否render ?
(Y) 更新UI -- componentDidUpdate
(N) 结束
**销毁:**componentWillUnmount
* 1.constructor
用途:用来初始化props,state(但此时不能调用setState) 和 写bind this
class B extends React.Component{
constructor(props){
super(props)
this.state = {
n:1,
m:2
}
this.onClick = this.onClick.bind(this)
}
}
* 2.shouldComponentUpdate / React.pureComponent
用途:返回 true不阻止UI更新 / false阻止UI更新
作用:可以手动设置判断是否要对组件进行更新,根据应用的场景灵活设置返回值,以避免不必要的更新
import React form 'react'
class App extends React.Component {
constructor(props){
super(props)
this.state = {
n : 1
}
}
onClick = ()=>{
this.setState(state =>({
n: state.n + 1
}))
this.setState(state =>({
n: state.n - 1
}))
}
shouldComponentUpdate(newProps,newState){
if(newState.n === this.state.n){
return false
}else{
return true
}
}
render(){
console.log('render 1次')
return(
<div>App
<div>
{{n}}
<button onClick={this.onClick}> + 1 </button>
</div>
</div>
)
}}
React 提供了内置功能 PureComponent ,可帮你直接判断state的值是否改变,如果没有改变则不执行
import React form 'react'
class App extends React.pureComponent {
constructor(props){
super(props)
this.state = {
n : 1
}
}
onClick = ()=>{
this.setState(state =>({
n: state.n + 1
}))
this.setState(state =>({
n: state.n - 1
}))
}
render(){
console.log('render 1次')
return(
<div>App
<div>
{{n}}
<button onClick={this.onClick}> + 1 </button>
</div>
</div>
)
}}
PureComponent 会在 render 之前对比新 state 和旧 state 的每一个 key,以及新 props 和旧 props 的每一个 key。
如果所有 key 的值全都一样,就不会 render;如果有任何一个 key 的值不同,就会 render。
*3.render
用途:用于展示视图,只能有一个根元素。如果需要多个根元素需要使用<React.Fragment></React.Fragment>标签
可以使用 if...else 、 ?:表达式 ,不能直接使用for循环,因为for没有返回值,需要使用数组,建议使用array.map循环
import React form 'react'class App extends React.Component { // ... render(){ //单个元素
return(<div>App<div>) // 多个元素
return(
<React.Fragment>
<div>11</div>
<div>22</div>
</React.Fragment>
// React.Fragment可简写为
<>
<div>11</div>
<div>22</div>
</>
)
// if...else 写法 if(...){
return ( ... )
}else{
return ( ... )
}
// 循环写法 map
return this.state.array.map(i => <div key={n}>{i}</div> )
}}
*4.componentDidMount()
用途:在元素插入页面后执行代码,这些代码依赖DOM,比如如果想获取某个元素的高度、宽度,最好在这里写
此处可以发起加载数据的AJAX请求(官方推荐)
首次渲染会执行此钩子
import React form 'react'
class App extends React.Component {
constructor(props){
super(props)
this.state = {
width:undefined
}
}
componentDidMount(){
const app = document.getElementById('app')
const {width} = app.getBoundingClientReact()
this.setState({width})
}
render(){
<div id="app"> APP </div>
}
}
可以使用React.createRef() 来获取元素,进行代码优化
这样写可以避免id声明冲突的问题
class App extends React.Component{
appRef = undefined constructor(props){
super(props)
this.state = {
width:undefined
}
this.appRef = React.createRef()
}
componentDidMount(){
const app = this.divRef.current
const {width} = app.getBoundingClientReact()
this.setState({width})
}
render(){
<div ref={this.appRef}> APP </div>
}}
*5.componentDidUpdate(prevProps,prevState,snapshot)
参数:prevProps更新前的props,prevState更新前的state
用途:在视图更新后执行代码。此处也可以发起AJAX请求,用于更新数据。
在此处setState可能会引起无限循环,除非放在if里。
若shouldComponentUpdate返回false,则不触发此钩子,原因是数据进行更新会触发此钩子。
首次渲染不会执行此钩子(因为首次加载没有任何更新)
*6.componentWillUnmount
用途:组件将要被移出页面然后被销毁时执行代码,unmount过的组件不会再次mount
例如 :在componentDidMount中监听了 window scoll 或 计时器timer 或 AJAX请求,那么就应该在 componentWillUnmount 进行取消,因为组件已经销毁,监听没有意义