react-native的组件生命周期总结:

 

生命周期 调用次数 能否使用setState()
getDefaultProps 1(全局调用一次)
getInitialState 1
componentWillMount 1
render >=1
componentDidMount 1
componentWillReceiveProps >=0
shouldComponentUpdate >=0
componentWillUpdate >=0
componentDidUpdate >=0
componentWillUnmount 1

注意:当调用this.setState时就会调用组件的render方法,但React框架会根据dom节点状态确定是否需要重新渲染

this.setState

this.setState用法

        this.setState(arg1,arg2),arg1可以是对象也可以是函数(必需),arg2是一个回调函数,在此函数中可以获取被setState更改后的state值,arg2可为空。

当arg1是对象时的写法:

this.setState({
    key : val
},()=>{
    console.log(this.state.key);
})
​

当arg1是函数时的写法:

//第一种写法(在更改state值之前执行一些操作)
this.setState(
    (prevState,props)=>{
        console.log(prevState);
        return { key : prevState.key+props.val };
},()=>{
    console.log(this.state.key);
}
);

​//第二种写法
this.setState(
    (prevState,props)=>({
        key : prevState.key+props.val
}),()=>{
    console.log(this.state.key);
}
);

this.setState的使用场景

        当通过this.state.key = val直接修改state值时,虽然可以更改state值,但是不会触发re-render对组件进行重新渲染,使用this.setState()更改state数据值,会触发re-render,组件会根据diff算法判断是否需要重新渲染。

this.setState()的异步更新

        this.setState()修改state值可能是异步更新,React 为了优化性能,有可能会将多个 setState() 调用合并为一次更新。

例如:

function incrementMultiple() { 

  this.setState({count: this.state.count + 1});
 
  this.setState({count: this.state.count + 1}); 

  this.setState({count: this.state.count + 1}); 
}

        函数incrementMultiple()执行之后,count的值没有增加3,而是增加了1,因为setState每次执行时依赖的值都是当前状态下的count,也就是三次更新操作所依赖的count值是相同的,setState将三次更新操作合并成了一个,所以函数执行完count值只增加了1。如果想要实现count值增加3的效果,setState在执行时所依赖的count值需要是前一个更新状态结束后的count值,即:

function incrementMultiple() { 

  this.setState((prevState)=>({count: prevState.count + 1}));
 
  this.setState((prevState)=>({count: prevState.count + 1})); 

  this.setState((prevState)=>({count: prevState.count + 1})); 
}

在React控制的事件处理程序中,this.setState()更改state值不是同步更新的:

preview

        在 React 的 setState 函数实现中,会根据一个变量 isBatchingUpdates 判断是直接更新 this.state 还是放到队列中回头再说,而 isBatchingUpdates 默认是 false,也就表示 setState 会同步更新 this.state,但是有一个函数 batchedUpdates,这个函数会把isBatchingUpdates 修改为 true,而当 React 在调用事件处理函数之前就会调用这个 batchedUpdates,造成的后果,就是由 React 控制的事件处理过程 setState 不会同步更新 this.state。(原文

组件的生命周期分为三个阶段:

一、实例化阶段:

        getDefaultprops():此方法在全局过程中只调用一次,在初始化时为组件设置初始值,可通过this.props进行访问,此方法在对象创建之前执行,因此不能在方法内对props进行修改,只能通过外部组件调用this.props进行修改任何由getDefaultProps()方法返回的对象在组件类中共享,而不是复制

var App = React.createClass({
  getDefaultProps : function () {
    return {
      title : 'Hello World'
    };
  },

  render: function() {
     return <h1> {this.props.title} </h1>;
   }
});

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

​

         React通过PropTypes提供了一种验证props的方式,当属性验证不通过时会报错。

var App = React.createClass({
  propTypes: {
    title: React.PropTypes.string.isRequired,
  },

  render: function() {
     return <h1> {this.props.title} </h1>;
   }
});

常用的PropTypes:

// 布尔值
React.PropTypes.bool                              
// 数值
React.PropTypes.number                            
// 字符串
React.PropTypes.string                            
// 函数
React.PropTypes.func                              
// 数组
React.PropTypes.array                             
// 对象
React.PropTypes.object                            
// 数值、字符串、DOM 元素及包含这些类型的数组
React.PropTypes.node                              
// React 元素
React.PropTypes.element                           
// 对象实例
React.PropTypes.instanceOf(Message)               
// 数组包含的值之一
React.PropTypes.oneOf(['News' 'Photos'])          
// 数组包含的类型之一
React.PropTypes.oneOfType([                       
    React.PropTypes.string,         
    React.PropTypes.number,         
    React.PropTypes.instanceOf(Message)                                  
])                                               
// 数值数组
React.PropTypes.arrayOf(React.PropTypes.number)   
// 对象的属性值为数值类型
React.PropTypes.objectOf(React.PropTypes.number)  
// 组合类型
React.PropTypes.shape({                           
    React.PropTypes.string                                   
    React.PropTypes.number                                   
})                                                 
// 任何类型,必填
React.PropTypes.any.isRequired                    
// 自定义规则
customProp: function(props propName componentName) {
    if (!/matchme/.test(props[propName])) {
        return new Error('Validation failed!');
    }
}

        getInitialState():此方法对组件状态进行初始化,可通过this.state进行访问,此方法与React.crea-teClass共同使用,是ES5的写法,而在ES6规范中直接通过构造函数constructor对this.state进行赋值初始化(推荐ES6写法)。

//ES5 规范

var App = React.createClass({ 
  propTypes: {
    title: PropTypes.string.isRequired
  },
  getInitialState () { 
    return {
      items: []
    }; 
  }
});

//ES6 规范
class App extends React.Component {
  constructor () {
    super()
    this.state = {
      items: []
    }
  }
});

通过getInitialState()实现反模式(通过this.props初始化state):

//反模式
getDefaultProps(){
    return {
        data: new Date()
    }
},
getInitialState(){
    return {
        day: this.props.date - new Date()
    }
},
render(){
    return <div>Day:{this.state.day}</div>
} 

        通过this.props来初始化state值并且后续不需要改变值时可以使用反模式,否则为了保证state值与派生出它的this.props同步,需要使用正确模式。

//正确模式
getDefaultProps(){
    return {
    day:new Date()
}
},

render{
    let day=this.props.day-new Date();
    return <div>Day:{day}</div>
} 

        componentWillMount():此方法在render之前调用,可以调用this.setState()在渲染前对组件state进行修改。此方法在react v16.3 版本发布后被去掉了,过度方案是在被去掉的函数前加UNSAFE_前缀继续使用。官网建议在constructor()中初始换state,异步拉取数据和定时器建议在component-DidMount()中实现。

        render():此方法会生成一个虚拟DOM(高效),表示组件的输出。在此方法中不可调用this.setState()进行修改。

此方法需要满足以下几点:

(1)只能通过this.props和this.state访问数据。

(2)可以返回null、false和任意React组件。

(3)只能返回一个顶级组件,不能返回一组元素

(4)不能改变组件状态。

(5)不能修改DOM输出。

        componentDidMount():此方法在组件渲染后调用一次,此方法在调用之前,已经渲染出真实的DOM,在此方法中可通过ReactDOM.findDOMNode()方法和refs属性获取到真实的DOM节点。

//ReactDOM.findDOMNode()

import ReactDOM from 'react-dom';
ReactDOM.findDOMNode(ReactComponent);

render(){
    //your view code
}

componentDidMount(){
    let dom=ReactDOM.findDOMNode(this);
}

//refs属性

render(){
    return <canvas ref='main'></canvas>
}

componentDidMount(){
    let main=this.refs.main;
}

二、存在阶段

        componentWillReceiveProps():此方法当组件接收新的props时执行,但此方法在react v16.3 版本发布后被去掉了,过度方案是在被去掉的函数前加UNSAFE_前缀继续使用。在此方法中可以调用this.setState()对组件state值进行修改。

componentWillReceiveProps(newProps){
    if(newProps.title!==undefined){
        this.setState({
            title : newProps.title
        });
    }
}

        shouldComponentUpdate():此方法当组件的props或者state发生变化时执行(初始化时不执行),返回一个bool值,当返回值为true时,componentWillUpdate()、render()和component-DidUpdate()将会被调用,也可以通过返回false阻止组件重新渲染。 

        componentWillUpdate():当shouldComponentUpdate()返回值为true时调用此方法,在render()方法之前执行,不可以在此方法中调用this.setState()方法改变组件state值,当此方法被调用后会自动将newState和newProps设置到this.state和this.props中。此方法在react v16.3 版本发布后被去掉了,过度方案是在被去掉的函数前加UNSAFE_前缀继续使用。

        componentDidUpdate():当shouldComponentUpdate()返回值为true时调用此方法,在render()方法之后执行,不可以在此方法中调用this.setState()方法改变组件state值。

三、销毁阶段

        componentWillUnMount():此方法在组件卸载之前调用,可以进行清理工作,如移除计时器等。 

        在componentDidMount()中增加的方法在卸载前都需要在componentWillUnMount()中进行清理。

当组件再次被加载时会再依次调用以下方法:

getInitialState()

componentWillMount()

render()

componentDidMount()

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐