React生命周期

1.react项目搭建

1)搭建react项目有两种:html中引入react和脚手架搭建react

2)react组件分为两种,函数式组件和类式组件

3)参考:React.js下载与使用

react JS文件CDN地址 

React官网找到CDN连接 React 官方中文文档 – 用于构建用户界面的 JavaScript 库 或者bootcdn查找cdn地址

   引入react可以直接指定cdn地址,也可以在浏览器输入下面地址下载保存为本地js然后html中引入。

<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

  注: bootcdn用来查找常见js库的cdn地址 BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务

2.react旧的生命周期 

 生命周期理解

  1. 组件从创建到死亡它会经历一些特定的阶段。
  2. React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。
  3. 我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。

1)render方法是将虚拟dom挂载(mount)到真实dom。

2)组件挂载时会执行一遍上图左侧方法。每个组件都会先进行一遍挂载mount,然后以后进行更新update。

  • 挂载时数据一般都是空。比如axios还没有请求回数据。如果挂载时数据person.name为undefined,会显示空,不显示内容。但是如果person.name中person为undefined,会报错。因此一般state初始化 state={person:{name:''}} 这样就不会报错。
<span>person.name</span>
  • 挂载时如果元素为null,react就不去渲染。如下为render里面代码,如果为null react就不去渲染。
name === undefined ?<Button>name</Button>:null

3)setState方法执行时,会执行setState--->shouldComponentUpdate--->componentWillUpdate---render--->componentDidUpdate; shouldComponentUpdate:是否要执行组件更新根据返回值boolean来判断是否进行更新

4)forceUpdate,会强制组件更新 forceUpdate--->componentWillUpdate---render--->componentDidUpdate

父组件render时,会执行右侧的方法

5)ReactDOM.unmountComponentAtNode(document.getElementById('demo'))会卸载组件。然后调用componentWillUnmount方法。

6)如下A组件为B组件的父组件。当父组件调用render方法时,子组件会调用对应方法。父组件render--->componentWillReceiveProps--->shouldComponentUpdate--->componentWillUpdate---render--->componentDidUpdate。

注意:componentWillReceiveProps当子组件收到的props更新时调用,第一次传递过来参数时不会调用,只有当第二次以后传递props才会调用。

7)所有方法分为mount、update两个时刻,即挂载组件和更新组件,分为will和did。render方法用来将虚拟dom转为真实dom;分为三个阶段,如下图:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title></title>
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.js"></script>
</head>
<body>
    <div id="example"></div>
    <script type="text/babel">
        class A extends React.Component {
            state = { carName: "奔驰" }
            changeCar = () => {
                this.setState({ carName: "奥拓" })
            }
            componentWillMount() {
                console.log("A---ComponentWillMount")
            }
            render() {
                return (
                    <div>
                        <div>我是A组件</div>
                        <button onClick={this.changeCar}>切换</button>
                        <B carName={this.state.carName} />
                    </div>
                )
            }
        }
        class B extends React.Component {
            componentWillMount() {
                console.log("B---ComponentWillMount")
            }

            componentWillReceiveProps() {
                console.log("B---componentWillRecieveProps()")
            }
            render() {
                return (
                    <div>B组件接收到的车还是{this.props.carName}</div>
                )
            }
        }
        ReactDOM.render(
            <A />,
            document.getElementById('example')
        );
    </script>
</body>

</html>

 3.render生命周期 (react 新版本使用)

旧版本生命周期中的componentWillMount、componentWillUpdate、componentWillRecieveProps在新版本被重命名。18. 版本将无法使用旧版本的名字。详情见官网

 

新旧版本生命周期相比

1)废弃三个钩子componentWillMount、componentWillUpdate、componentWillRecieveProps

2)新增两个钩子getDerivedStateFromProps、getSnapsshowBeforeUpdate。这两个不常用

3)getDerivedFromProps 唯一的作用就是用于从props得到一个衍生的state。不常用,仅用在组件的state取决于pros的情况。如下示例

  • getDerivedFromProps可以接收props和state两个参数。props为父组件调用子组件时传入的;state为子组件自身的state属性
  • 无论是子组件调用了 setState(),、接收父组件的 props 发生了变化, 或是父组件的更新都会导致子组件上的 getDerivedStateFromProps被触发。

  • 如果在getDerivedStateFromProps对本组件的state做了初始化,本组件一个setState就引起调用getDerivedStateFromProps,从而引起本组件state的初始化。如果不想初始化,必须加一个state属性,在getDerivedStateFromProps进行判断,来决定更不更新。如下所示,本组件每次调用setState时设置一下setStateOccurs值,从而可以实现setState引起的getDerivedFromProps调用时不执行state初始化。

static getDerivedStateFromProps(props, state) {
        const { surveySuspectInfo, isSubmit, propsUpdate } = props
        //允许接受更新
        if (propsUpdate) {
            //案件名称 案件类型 交案单位 负责人 联系方式 立案时间
            state = {
                ...state,
                surveySuspectInfo,
                selectedRelPersonIndex: 0,
            }
            return state;
        }
        //如果是提交 不要让父组件props更新传过来
        if (state.setStateOccurs || isSubmit) {
            state = {
                ...state,
                setStateOccurs: false
            }
            return state
        } else {
            //案件名称 案件类型 交案单位 负责人 联系方式 立案时间
            state = {
                ...state,
                surveySuspectInfo,
                selectedRelPersonIndex: 0,
            }
            return state;
        }
    }
 changeTabButton = (activeKey) => {
        //activeKey和相关人列表的索引一样
        this.setState({ selectedRelPersonIndex: +activeKey , setStateOccurs: true, propsUpdate_rel: true }, () => {
            this.setState({ propsUpdate_rel: false, setStateOccurs: true })
        })
    }

  • 子组件调用setState,getDerivedStateFromProps(props,state)被触发,此时的state是更新后的值。

  • getDerivedFromProps(nextProps,preState) nextProps父组件传过来的props,preState为当前子组件的state值。有时需要进行一些判断来决定更不更新子组件state。如果不更新需要return null代表不更新

<script type="text/babel">
        class A extends React.Component {
            state = {count:0}
            static getDerivedStateFromProps(props,state){
                console.log(props + state )
                return props
            }
            render() {
                return (<div>{this.state.count}</div>)
            }
        }

        ReactDOM.render(
            <A count={111} />,
            document.getElementById('example')
        )
</script>

4.总结

重要的勾子

  1. render:初始化渲染或更新渲染调用
  2. componentDidMount:开启监听, 发送ajax请求
  3. componentWillUnmount:做一些收尾工作, 如: 清理定时器

即将废弃的勾子

  1. componentWillMount
  2. componentWillReceiveProps
  3. componentWillUpdate

现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。

5.虚拟DOM Diff算法

理解:react中每个标签都有一个key。react会将新旧虚拟dom相同key的标签进行比较,如果内容变了就将新虚拟dom替换掉旧虚拟dom,并更新到真实dom 。这样可以有效减少更新真实dom操作。比如:一个ul列表,几千条。可能每次前边的数据都没变化,就不再需要更新真实dom。

数组的index作为标签的key的问题 

1)persons = [{name:'fang',id:1}]   <Demo persons={persons}> 

2)persons=[{name:'yang',id:2},...persons] <Demo persons={persons}>  此时会出现问题,因为Demo中ul的li标签使用index作为key。fang的key为1,yang的key也是1,那么key就重复了,也就回报错。所以,此处使用数据自身携带的唯一的id作为key值最好。

import React, { Component } from 'react'

export default class Demo extends Component {
    render() {
        const {persons} = this.state
        return (
            <ul>
                persons.map((person,index)=>{
                    return (<li key={index}> person.name</li>)
                })
            </ul>
        )
    }
}

6.父子组件生命周期执行顺序 

父组件A,子组件B ,A组件的render里面有多个B。

A组件render时,遇到B组件就先去执行B组件的render方法,B生命周期结束,然后继续A组件render,再次遇见B就去执行B的生命周期。直至A组件生命周期结束。

如何实时获取子组件的变量值?

         父组件A,子组件B ,A组件的render里面有多个B。

        A通过传递一个回调函数给B,让B的变量发生变化时,调用A传递的回调函数,从而实现将变量传给A,A此时可以通过state或者成员变量存储传递回来的值。最后在componentDidUpdate获取到所有B组件的变量值,做一些逻辑处理。

        A组件render里面包含的每个B组件都是一个B组件建立的新对象。B组件彼此之间互不影响。A组件只有第一次render时新建B的组件对象,以后render只是传递值给B组件对象。

        组件对象也有自己的成员变量,可以进行赋值。

export default class PersonInfo extends Component {
    //成员变量 用来存储所有子组件的值
    addAreaDataList_suspect = []
    componentDidUpdate() {
        const { addAreaDataList_suspect } = this
        //axios接口 完成数据提交
        setSurveySuspectInfo(addAreaDataList_suspect)
        //清空addAreaDataList
        this.addAreaDataList_suspect = []
    }
    //子组件调用  增加需要提交的多媒体信息 嫌疑人:type=61身份证 71生活照 ;
    realTimeUpdateSuspect = (fileList, fileType) => {
        let { addAreaDataList_suspect } = this
        addAreaDataList_suspect = [...addAreaDataList_suspect, ...fileList]
        this.addAreaDataList_suspect = addAreaDataList_suspect
    }

    render() {
        return (
            <div>
                <div style={{ display: 'flex', flexDirection: 'column', width: '120%', marginLeft: '-20%' }}>
                    <ImageUpload relTimeUpdata={this.realTimeUpdateSuspect} />
                    <span className='tag'>身份证照</span>
                </div>
                <div style={{ display: 'flex', flexDirection: 'column', width: '120%', marginLeft: '-20%' }}>
                    <ImageUpload relTimeUpdata={this.realTimeUpdateSuspect} descType='6' />
                    <span className='tag'>生活照</span>
                </div>
            </div>
    }
}
import React, { Component } from 'react'

export default class ImageUpLoade extends Component {
    state = {
        imgs: []
    }
    addImgs= () => {
        const { relTimeUpdata } = this.props
        const { imgs} = this.state
        imgs= [...imgs,{file_name:'图1',id:'1221212'}]
        relTimeUpdata(count,'img')
        this.setState({ imgs})

    }
    render() {
        return (
            <div>
                <Button onClick={this.addImgs}>增加图片</Button>
                <Button onClick={this.addAudio}>增加语音</Button>
            </div>
        )
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fang·up·ad

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值