0-5【React】Class 组件(生命周期)

生命周期

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组件也有这些过程,可以看作高级的div

1.React的生命周期

  • 在对应的时期会调用相应函数
constructor()   //创建组件时调用的函数:在这里初始化state
shouldComponentUpdate()  //是否更新组件:return false 阻止更新,还要return true
render()  //渲染:创建虚拟DOM
componentDidMount()  //组件挂载完成:已经出现在页面
componentDidUpdate()  //组件更新完成
componentWillUnmount()  //组件将要卸载

1.constructor

  • 初始化 props
  • 初始化 state
    注意:这里的初始化只能用 this.state,不能用setState初始化
  • 用来写 bind this
constructor(){
  //其他代码略
  this.onClick = this.onClick.bind(this)
}
//等价于新语法:箭头函数不改变this
onClick = ()=>{}
constructor(){//其他代码略}
  • constructor可不写
    只有在需要初始化state才需要些constructor
    只有props不用写

2.shouldComponentUpdate

  • 返回 true 表示不阻止UI更新
  • 返回 false 表示阻止UI更新
  • shouldComponentUpdate接收两个参数
    arguments[0]:newProps
    arguments[1]:newState
    不用也要占位
    旧的数据就是:this
  • shouldComponentUpdate有什么用?
    答:它允许我们手动判断是否要进行组件更新,我们可以根据应用场景灵活的设置返回值,避免不必要的更新
    ——Vue就不需要判断,因为它监听数据,我们修改了数据它就知道自动更新
  • 代码
    如:当产生的新对象和旧对象内容一样(地址是不同的),就阻止更新
shouldComponentUpdate(newProps,newState){
    //这里的newProps虽然没有用到,但不能删掉,这是占位的
    //因为要用的是第二个参数,根据位置来定的:arguments[1]
    if(newState.n === this.state.n){
        //当新state和旧state一样,就不更新
        return false 
    }else{
        return true
    }
}
  • 图解
    多余的一步就是:render函数调用
    在这里插入图片描述
  • React内置该功能:PureComponent
    ——有了这个就不用对比新旧state返回ture和false,能在绝大多数情况代替shouldComponentUpdate
    PureComponent 会在 render 之前对比新 state 和旧 state 的每一个 key,以及新 props 和旧 props 的每一个 key。
    如果所有 key 的值全都一样,就不会 render;如果有任何一个 key 的值不同,就会 render。
class App extends React.PureComponent{
  //代码略
}

3.render

  • 展示视图
    return (<div>...</div>)
    1.这不是DOM元素,而是一个表示DOM元素的对象
    2.称这个对象为:虚拟DOM
    3.虚拟DOM:就是把HTML转化为了对象
    ——对象里面有属性:type、props等
  • 只能有一个根元素
    意思是:标签只能嵌套,不能并列
  • 如果有两个根元素,就要用<React.Fragment>包起来
    1.这个元素只是用来做占位,渲染的时候这个元素是不存在的
    2.不需要创建一个多余的div
  • <React.Fragment>可以缩写成<></>
return (
  <>
      <div>hi</div>
	  <div>App
		<div>
		  {this.state.n}
		  <button onClick={this.onClick}>+1</button>
		</div>
	  </div>
 </>
)

在这里插入图片描述

  • 小技巧:render里面可以写
    render(){}当做一个JS正常函数,将标签看作变量来写
    ——赋值: message = <div>hi</div>,return:{ message }
    1.if...else
    2.?:表达式
    3.不能直接写for循环:因为for循环没有return,在第一次return的时候,整个循环就结束了
    ——解法一:创建一个空数组,遍历的标签都 push 到空数组里,return 数组
    ——解法二(推荐):使用map,map有返回值
    array.map(n=><span>{n}</span>)
  • ?:表达式
render(){
   return (
        <>
          { this.state.n%2===0?<div>偶数</div>:<div>奇数</div>}
          <button onClick={this.onClick}>+1</button>
        </>
     )
}
  • array.map(循环)
    注意:每个元素都有一个独一无二的key
render(){
  //使用map对数组元素进行包裹
    return this.state.array.map(n=><span key={n}>{n}</span>)
}

在这里插入图片描述
4.componentDidMount()

  • 组件已经挂载
  • 在元素插入页面后执行代码,这些代码依赖DOM
    比如:想要获取div的高度
    document.getElementById等一系列的代码中,document是文档,必须要元素出现在页面中才能获取
  • 获取的两种方法
    1.ID:document.getElementById(‘xxx’)
    2.Ref:可以解决id冲突的问题,因为ref相当于是实例上的属性
    ——比ID更装逼的一种写法
class Demo extends React.Component {
  divRef = undefined; // 好习惯,提前写在这里,告诉别人这里有个ref
  constructor(props) {
    super(props);
    // 创建引用
    this.divRef = React.createRef();
  }
  componentDidMount() {
  	// 页面挂载后才能获取到元素
    const div = this.divRef.current;
    const { width } = div.getBoundingClientRect();
  }
  render() {
    return <div ref={this.divRef}>你好,这里是引用组件</div>;
  }
}
  • 此处可以发起加载数据的AJAX请求
    问:如果想要发送加载数据的AJAX的请求,应该放在哪个生命周期里
    答:componentDidMount()
  • 首次渲染会执行此钩子
  • componentDidMount()函数中,没有接收参数
    任何东西通过 this. 来获取
componentDidMount(){
    //获取到当前的div赋值
    const div = this.divRef.current
    //析构赋值:获取div的宽度
    const {width} = div.getBoundingClientRect()
    this.setState({width})
}
render(){
    return (
        <div ref={this.divRef}>Hello world,宽度为{this.state.width}px</div>
    )
}

5.componentDidUpdate()

  • 在视图更新后执行代码
  • 此处也可以发起AJAX请求,用于更新数据请求
    比如:用户ID改变,获取新的用户信息
  • 首次渲染不会执行此钩子
    因为首次渲染不会更新任何东西
  • 在此处setState可能会引起无限循环
    1.在更新里改数据,改了又更新
    2.因此:最好不要再 update 里面 setState,除非有条件判断(if)可以跳出循环
  • 若 shouldComponentUpdate 返回false,则不会触发此钩子
    阻止更新
  • 接收3个参数
    1.preProps
    2.prevState
    3.snapshot(不用)

6.componentWillUnmount

  • 组件将要被移出页面然后销毁时执行代码
    1.移出页面:DOM到内存
    2.销毁:从内存中干掉
  • unmount 过的组件不会再次 mount
    1.死后不能复生
    2.只能重新创建
  • 使用(一般不用,只是占点内存)
    这个是用于消除之前做过可能会产生后果的事情
    如果:在componentDidMount中创建了 事件监听/Timer/AJAX请求 ,那么就要在componentWillUnmount中取消 监听/Timer/AJAX请求
  • 原则:谁污染谁治理

7.总结

  • 一般不会手动销毁,只有后期有路由的时候才会销毁

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值