react 生命周期

一个React组件的性命周期分为三个部份:实例化、存在期和烧毁时。

实例化阶段

  1. 客户端衬着时,以下顺次被挪用

    • getDefaultProps()
    • getInitialState()
    • componentWillMount()
    • render()
    • componentDidMount()
  2. 服务端衬着

    • getDefaultProps()
    • getInitialState()
    • componentWillMount()
    • render()

注重:componentDidMount()不会再服务端被衬着;

getDefaultProps

关于每一个组件实例来讲,这个要领只会挪用一次,该组件类的一切后续运用,getDefaultPops 将不会再被挪用,其返回的对象可以用于设置默许的props值。

var Hello = React.creatClass({
    getDefaultProps: function(){
        return {
            name: 'pomy',
            git: 'dwqs'
        }
    },
    
    render: function(){
        return (
            <div>Hello,{this.props.name},git username is {this.props.dwqs}</div>
        )
    }
});

ReactDOM.render(<Hello />, document.body);

也可以在挂载组件的时刻设置 props。

var data = [{title: 'Hello'}];
<Hello data={data} />

或许挪用 setProps (平常不须要挪用)来设置其 props

var data = [{title: 'Hello'}];
var Hello = React.render(<Demo />, document.body);
Hello.setProps({data:data});

但只能在子组件或组件树上挪用 setProps。别挪用 this.setProps 或许 直接修正 this.props。将其当作只读数据。

React经由过程 propTypes 供应了一种考证 props 的体式格局,propTypes 是一个设置对象,用于定义属性范例:

var survey = React.createClass({
    propTypes: {
        survey: React.PropTypes.shape({
            id: React.PropTypes.number.isRequired
        }).isRequired,
        onClick: React.PropTypes.func,
        name: React.PropTypes.string,
        score: React.PropTypes.array
        ...
    },
    
    //...
})

或许

import React, { Component } from 'react'
import PropTypes from 'prop-types'

class BetterImage extends Component{...}

BetterImage.PropTypes={
  src: PropTypes.string,
  center: PropTypes.bool,
  loadingImage: PropTypes.string,
  defaultImage: PropTypes.string,
  onLoad: PropTypes.func,
  onError: PropTypes.func,
  onComplete: PropTypes.func
}
BetterImage.defaultProps={
  ....
}

getInitialState

关于组件的每一个实例来讲,这个要领的挪用有且只要一次,用来初始化每一个实例的 state,在这个要领里,可以接见组件的 props。每一个React组件都有本身的 state,其与 props 的区分在于 state只存在组件的内部,props 在一切实例中同享。

getInitialState 和 getDefaultPops 的挪用是有区分的,getDefaultPops 是关于组件类来讲只挪用一次,后续该类的运用都不会被挪用,而 getInitialState 是关于每一个组件实例来讲都邑挪用,而且只调一次。

var LikeButton = React.createClass({
  //初始化State
  getInitialState: function() {
    return {liked: false};
  },
  
  handleClick: function(event) {
    //设置修正State
    this.setState({liked: !this.state.liked});
  },

  render: function() {
    var text = this.state.liked ? 'like' : 'haven\'t liked';
    return (
      <p onClick={this.handleClick}>
        You {text} this. Click to toggle.
      </p>
    );
  }
});

ReactDOM.render(
  <LikeButton />,
  document.getElementById('example')
);

每次修正 state,都邑从新衬着组件,实例化后经由过程 state 更新组件,会顺次挪用以下要领:

1、shouldComponentUpdate
2、componentWillUpdate
3、render
4、componentDidUpdate
  • componentWillMount

在衬着前挪用,在客户端也在服务端。React 官方正式宣布了 v16.3 版本。在这次的更新中,除了前段时候被热闹议论的新 Context API 以外,新引入的两个性命周期函数 getDerivedStateFromProps,getSnapshotBeforeUpdate 以及在将来 v17.0 版本中行将被移除的三个性命周期函数 componentWillMount,componentWillReceiveProps,componentWillUpdate .

在这个性命周期中你会碰到一下题目:

a.首屏无数据致使白屏
在 React 运用中,很多开发者为了防止第一次衬着时页面因为没有猎取到异步数据致使的白屏,而将数据要求部份的代码放在了 componentWillMount 中,愿望可以防止白屏并提早异步要求的发送时候。但事实上在 componentWillMount 实行后,第一次衬着就已最先了,所以假如在 componentWillMount 实行时还没有猎取到异步数据的话,页面初次衬着时也仍然会处于没有异步数据的状况。换句话说,组件在初次衬着时总是会处于没有异步数据的状况,所以不管在那里发送数据要求,都没法直接处置惩罚这一题目。而关于提早发送数据要求,官方也勉励将数据要求部份的代码放在组件的 constructor 中,而不是 componentWillMount。
假如为了改良用户体验曾用过的处置惩罚要领有两个:

要领一:异步要求组件,运用nprogress 增加加载动画;

import React, { Component } from 'react'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import './customNprogress.styl'

NProgress.configure({ showSpinner: false })

export default function asyncComponent(importComponent) {
  class AsyncComponent extends Component {
    state = {
      component: null
    }

    async componentDidMount() {
      NProgress.start()
      const { default: component } = await importComponent()
      NProgress.done()

      this.setState({ component })
    }

    render() {
      const C = this.state.component

      return C ? <C {...this.props} /> : null
    }
  }

  return AsyncComponent
}

const AsyncNotFound = asyncComponent(() => import(/* webpackChunkName: "NotFound" */ '@/routes/NotFound'))

要领二:运用 onreadystatechange 去监听 readyState,在资本加载完成之前加载一个只要框架的静态页面,页面不要求数据。当数据要求完成今后再将路由切换到实在的首页。

  function listen () {
    if (document.readyState == 'complete') { // 资本加载完成
        ReactDom.render(
            <Provider store={store}>
                <Router>
                    <Route path="/" component={Index}/>
                </Router>
            </Provider>,
            document.getElementById('root')
        )
    } else { // 资本加载中
        ReactDom.render(
            <Provider store={store}>
                <Router>
                    <Route path="/" component={FirstScreen}/>
                </Router>
            </Provider>,
            document.getElementById('root')
        )
    }
}

document.onreadystatechange = listen

详细参考处置惩罚React首屏加载白屏的题目

b.事宜定阅

另一个罕见的用例是在 componentWillMount 中定阅事宜,并在 componentWillUnmount 中取消掉响应的事宜定阅。但事实上 React 并不可以保证在 componentWillMount 被挪用后,统一组件的 componentWillUnmount 也肯定会被挪用。一个当前版本的例子如服务端衬着时,componentWillUnmount 是不会在服务端被挪用的,所以在 componentWillMount 中定阅事宜就会直接致使服务端的内存走漏。另一方面,在将来 React 开启异步衬着形式后,在 componentWillMount 被挪用今后,组件的衬着也很有能够会被其他的事务所打断,致使 componentWillUnmount 不会被挪用。而 **componentDidMount 就不存在这个题目,在 componentDidMount 被挪用后,componentWillUnmount 肯定会随后被挪用到,并依据详细代码清撤除组件中存在的事宜定阅。**

render

该要领会建立一个假造DOM,用来示意组件的输出。关于一个组件来讲,render要领是唯一一个必需的要领。render要领须要满足下面几点:

  • 只能经由过程 this.props 和 this.state 接见数据(不能修正)
  • 可以返回 null,false(这类场景下,react衬着一个<noscript>标签,当返回null或许false时,ReactDOM.findDOMNode(this)返回null) 或许任何React组件
  • 只能涌现一个顶级组件,不能返回一组元素
  • 不能转变组件的状况
  • 不能修正DOM的输出

render要领返回的效果并非真正的DOM元素,而是一个假造的表现,相似于一个DOM tree的构造的对象。react之所以效率高,就是这个缘由。

render实行状况以下:

 1. 初次加载
 2. setState转变组件内部state。
    注重: 此处是说经由过程setState要领转变。
 3. 吸收到新的props

注重:因为数据是异步的状况,会致使组件反复衬着

componentDidMount

该要领不会在服务端被衬着的过程当中挪用。该要领被挪用时,已衬着出实在的 DOM,可以再该要领中经由过程 this.getDOMNode() 接见到实在的 DOM(引荐运用 ReactDOM.findDOMNode())。

var data = [..];
var comp = React.createClass({
    render: function(){
        return <imput .. />
    },
    componentDidMount: function(){
        $(this.getDOMNode()).autoComplete({
            src: data
        })
    }
})

因为组件并非实在的 DOM 节点,而是存在于内存当中的一种数据构造,叫做假造 DOM (virtual DOM)。只要当它插进去文档今后,才会变成实在的 DOM 。偶然须要从组件猎取实在 DOM 的节点,这时候就要用到 ref 属性:

var Area = React.createClass({
    render: function(){
        this.getDOMNode(); //render挪用时,组件未挂载,这里将报错
        
        return <canvas ref='mainCanvas'>
    },
    componentDidMount: function(){
        var canvas = this.refs.mainCanvas.getDOMNode();
        //这是有用的,可以接见到 Canvas 节点
    }
})

须要注重的是,因为 this.refs.[refName] 属性猎取的是实在 DOM ,所以必需比及假造 DOM 插进去文档今后,才运用这个属性,不然会报错。假如ref回调函数以inline函数的体式格局来指定,那末在组件更新的时刻ref回调会被挪用2次。第一次回调的时刻传入的参数是null,而第二次的时刻才真正的传入DOM节点

更多相识ref运用
从React官方文档看 refs 的运用和将来
猎取实在dom,并猎取dom css 三种要领

存在期

此时组件已衬着好而且用户可以与它举行交互,比方鼠标点击,手指点按,或许别的的一些事宜,致使运用状况的转变,你将会看到下面的要领顺次被挪用;

  1. componentWillReceiveProps()
  2. shouldComponentUpdate()
  3. componentWillUpdate()
  4. render()
  5. componentDidUpdate()

componentWillReceiveProps

当props发作变化时实行,初始化render时不实行,在这个回调函数内里,你可以依据属性的变化,经由过程挪用this.setState()来更新你的组件状况,旧的属性照样可以经由过程this.props来猎取,这里挪用更新状况是平安的,并不会触发分外的render挪用。

componentWillReceiveProps: function(nextProps){
    if(nextProps.checked !== undefined){
        this.setState({
            checked: nextProps.checked
        })
    }
}

相识更多点击此处

shouldComponentUpdate

shouldComponentUpdate函数是重衬着时render()函数挪用前被挪用的函数,它吸收两个参数:nextProps和nextState,离别示意下一个props和下一个state的值。而且,当函数返回false时刻,阻挠接下来的render()函数及背面的 componentWillUpdate,componentDidUpdate 要领的挪用,阻挠组件重衬着,而返回true时,组件照旧重衬着。

相识更多点击此处–真的讲的好

componentWillUpdate

这个要领和 componentWillMount 相似,在组件吸收到了新的 props 或许 state 行将举行从新衬着前,componentWillUpdate(object nextProps, object nextState) 会被挪用,注重不要在此方面里再去更新 props 或许 state。

componentDidUpdate

这个要领和 componentDidMount 相似,在组件从新被衬着今后,componentDidUpdate(object prevProps, object prevState) 会被挪用。可以在这里接见并修正 DOM。

烧毁

componentWillUnmount

每当React运用完一个组件,这个组件必需从 DOM 中卸载后被烧毁,此时 componentWillUnmout 会被实行,完成一切的清算和烧毁事情,在 componentDidMount 中增加的使命都须要再该要领中打消,如建立的定时器或事宜监听器。

当再次装载组件时,以下要领会被顺次挪用:

1、getInitialState
2、componentWillMount
3、render
4、componentDidMount

React v.16性命周期

constructor(props) // 初始化参数

componentWillMount()

render() // 第一次衬着 

componentDidMount()

**当父组件向子组件传入props发作转变后,顺次挪用**

componentWillReceiveProps(nextProps)

shouldComponentUpdate(nextProps, nextState) 

componentWillUpdate()

render() //子组件更新衬着

componentDidUpdate()

**当组件本身state发作变化后**

componentWillUpdate()

render() //组件再次更新衬着

componentDidUpdate()


当组件卸载

componentWillUnmount()

与低于React16版本的比较

  1. React16新的性命周期弃用了componentWillMount、componentWillReceiveProps,componentWillUpdate
  2. 新增了getDerivedStateFromProps、getSnapshotBeforeUpdate来替代弃用的三个钩子函数(componentWillMount、componentWillReceivePorps,componentWillUpdate)
  3. React16并没有删除这三个钩子函数,然则不能和新增的钩子函数(getDerivedStateFromProps、getSnapshotBeforeUpdate)混用,React17将会删除componentWillMount、componentWillReceivePorps,componentWillUpdate
  4. 新增了对毛病的处置惩罚(componentDidCatch)

相干文章

谁人性命周期要领更适合要求数据
react服务端衬着
来谈谈Reactv16.3新性命周期知识点及碰到的题目
React16版性命周期

    原文作者:javascriptMen
    原文地址: https://segmentfault.com/a/1190000018743954
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞