react学习3—生命周期

文章详细阐述了React组件的生命周期,包括旧版和新版生命周期方法的使用,如挂载、更新和卸载阶段的关键函数。同时,讨论了key在React列表渲染中的重要性,以及为何不应使用index作为key,以及diffing算法的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.引入

挂载:mount
卸载:unmount

//卸载组件
death=()=>{
   //卸载组件
   ReactDOM.unmountComponentAtNode(document.getElementById('test'))
}
<script type="text/babel">
    //创建组件
    class Life extends React.Component{

      state={opacity:1}

      death=()=>{
        // //清除定时器
        // clearInterval(this.timer)
        //卸载组件
        ReactDOM.unmountComponentAtNode(document.getElementById('test'))
      }

      //组件挂载完毕后调用,只调用一次
      componentDidMount(){  
        this.timer=setInterval(()=>{
          //获取原状态
          let {opacity} = this.state;
          //减小0.1
          opacity -=0.1
          if(opacity <=0){
            opacity =1
          }
          //设置
          this.setState({opacity})
        },200)
      }
      
      //组件将要被卸载
      componentWillUnmount(){
        clearInterval(this.timer)
      }
    
      //render 初始化渲染+更新
      render(){
        return(
          <div>
            <h2 style={{opacity:this.state.opacity}}>React学不会怎么办</h2>  
            <button onClick={this.death}>不会啊</button>
          </div>
        )
      }
    }
    //渲染组件
    ReactDOM.render(<Life /> ,document.getElementById('test'))
  </script>

生命周期回调函数/生命周期钩子函数/生命周期函数/生命周期钩子

生命周期(旧)

在这里插入图片描述
总结:
生命周期分为三个阶段
1.初始化阶段 React.Render() 触发——初次渲染
(1)constructor()
(2)componentWillMount()–即将废弃
(3)render()
(4)componentDidMount()----常用,一般做初始化的事,例如:开启定时器,订阅消息,发送网络请求
2.更新阶段 组件内部this.setState()或父组件render()触发
(1)shouldComponentUpdate()
(2)componentWillUpdate()–即将废弃
(3)render()
(4)componentDidupdate()
3.卸载阶段 ReactDOM.unmountComponentAtNode触发
(1)componentWillUnmount()—常用,一般做收尾的事,例如:关闭定时器,取消订阅消息

生命周期(新)

在这里插入图片描述
区别:新生命周期废弃了3个钩子,新增了2个钩子(几乎不用)getDerivedStateFromProps、getSnapshotBeforeUpdate
1、getDerivedStateFromProps——适用于state在任何时候都取决于props,一般不用
derived(派生的)

  <script type="text/babel">
    //创建组件
    class Count extends React.Component{
      constructor(props){
        console.log('count-constructor')
        super(props)
        //初始化状态
        this.state={count:0}
      }

      static getDerivedStateFromProps(props,state){
        console.log('count-getDerivedStateFromProps',props,state)
        return props
      }
      render(){
        console.log('count-render')
        const {count} =this.state
        return(
          <div>
            <h2>当前求和为:{count}</h2>  
            <button onClick={this.add}>点我+1</button>
          </div>
        )
      }
    }
    //渲染组件
    ReactDOM.render(<Count count='133'/>,document.getElementById('test'))
  </script>

挂载:
在这里插入图片描述
2、getSnapshotBeforeUpdate —不常见
Snapshot快照

//更新之前获取快照
getSnapshotBeforeUpdate(){
    console.log('getSnapshotBeforeUpdate')
    return 'atGuigu'
}

//组件更新完毕
componentDidUpdate(prevProps,prevState,snapshotValue){ 
  console.log('count-componentDidUpdate',prevProps,prevState,snapshotValue)
}

    ReactDOM.render(<Count count='133'/>,document.getElementById('test'))

在这里插入图片描述
案例:实现列表数自增和滚动到某位置视图不变
在这里插入图片描述

 <script type="text/babel">
    //创建组件
    class NewsList extends React.Component{

      state={newsArr:[]}

      getSnapshotBeforeUpdate(){
        return this.refs.list.scrollHeight
      }
      componentDidUpdate(prevProps,prevState,height){
        this.refs.list.scrollTop += this.refs.list.scrollHeight -height
      }

      componentDidMount(){
        setInterval(()=>{
          //获取原状态
          const {newsArr} = this.state
          //模拟一条新闻
          const news = '新闻'+(newsArr.length+1)
          //更新状态
          this.setState({newsArr:[news,...newsArr]})
        },1000)
      }
      render(){
        return(
          <div className="list" ref="list">
            {
              this.state.newsArr.map((n,index)=>{
                return(<div className="news" key={index}>{n}</div>)
              })
            }
          </div>
        )
      }
    }

    //渲染组件
    ReactDOM.render(<NewsList />,document.getElementById('test'))
  </script>

总结
1.初始化阶段:有React.render()触发——初次渲染
(1)constructor()
(2)getDerivedStateFromProps()
(3)render()
(4)componentDidmount() ——常用 开启监听,发送ajax请求
2.更新阶段 组件内部this.setState()或父组件render()触发
(1)getDerivedStateFromProps()
(2)shouldComponentUpdate()
(3)render()
(4)getSnapshotBeforeUpdate()
(5)componentDidupdate()
3.卸载阶段 ReactDOM.unmountComponentAtNode触发
(1)componentWillUnmount()——常用 收尾

diffing算法

react/vue的key有什么作用,内部原理是什么?/为什么遍历列表时,key最好不用index?
解答:key是虚拟DOM对象的标识,在更新显示时起着极其重要的作用
1、当状态中的数据发生改变时,react会根据新数据生成新的虚拟DOM,
随后react进行新和旧虚拟DOM的diff比较,规则如下:
(1)若虚拟DOM中找到了和虚拟DOM相同的key:
Ⅰ.若虚拟DOM中内容没变,直接使用之前的真实DOM;
Ⅱ.若虚拟DOM中内容变了,则生成新的真实DOM,随后替换到页面中之前的真实DOM
(2)若旧虚拟DOM中未找到与新虚拟DOM相同的key:
根据数据创建新的真实DOM,随后放在页面

2、用index作为key可能引发的问题:
(1)对数据进行:逆序增加、删除等改变顺序的操作;==》效率低
(2)页面有输入类DOM:会产生错误DOM更新; =》界面有问题
仅用于列表展示,是没有问题的

3、开发中如何选择key?
(1)有唯一标识,则用唯一标识
(2)仅仅简单展示列表

举例:
在这里插入图片描述

  <script type="text/babel">
    class Person extends React.Component{
      state={
        persons:[
        {id:'1',name:'小张',age:18},
        {id:'2',name:'小李',age:19},
        ]
      }
      add=()=>{
        const {persons} = this.state;
        const p = {id:persons.length+1,name:'小王',age:20}
        this.setState({persons:[p,...persons]})
      }
      render(){
        return (
          <div>
            <h2>展示人员信息</h2>
            <button onClick={this.add}>添加一个小王</button>
            <h3>index索引值作为key</h3>
            <ul>
              {
                this.state.persons.map((personObj,index)=>{
                  return <li key={index}>{personObj.name}---{personObj.age} <input type="text"/></li>
                })
              }  
            </ul> 
            <hr /> 
            <h3>id作为key</h3>
            <ul>
              {
                this.state.persons.map((personObj)=>{
                  return <li key={personObj.id}>{personObj.name}---{personObj.age} <input type="text"/></li>
                })
              }  
            </ul> 
          </div>
        )
      }
    }
 
    ReactDOM.render(<Person/>,document.getElementById('test'))
  </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值