React的生命周期与应用

  • 一、react组件的两种创建写法
  • 二、组件的生命周期在不同状态下的执行顺序
  • 三、组件各生命周期的应用

一、react组件的两种创建写法

第一种是 React.createClass

1

2

3

4

5

6

7

8

9

10

11

12

React.createClass({

    getDefaultProps() {

        return {

            key1:value1

        }

    },

    getInitialState() {

        return {

            state1:state1

        }

    }

});

 

第二种是用类的继承

1

2

3

4

5

6

7

8

9

10

11

12

export default class Test1 extends React.Component {

    constructor (props) {

        super(props);

        this.state = {

            state1: state1

        }

    }

    static defaultProps = {

        data: 2,

    };

 

}

 

getDefaultProps、getInitialState是在createClass时调用的方法,而在继承component类时,getDefaultProps方法对应给类添加静态属性  defaultProps ,getInitialState 对应在类的构造函数中设置  state属性

 

二、组件的生命周期在不同状态下的执行顺序

组件首次装载(first-Mount): getDefaultProps() → getInitialState() → componentWillMount() → render()  →  componentDidMount()

卸载组件时(Unmount):componentWillUnmount()

当重新装载组件时(Re-Mount):getInitialState()→componentWillMount()→render() → componentDidMount(),但并不执行 getDefaultProps; defaultProps是放在组件类上的static属性

当再次渲染组件时(Re-Render),此时按顺序执行 componentWillReceiveProps(nextProps )(组件接收到新的props才会调用,只是改变state时不调用)→ shouldComponentUpdate→ componentWillUpdate→ render →  componentDidUpdate。

 

在单页应用中,用react-router的history做页面跳转时,是将当前route的所有组件卸载,再跳转回来时是重新装载组件,而不是首次装载。

 

三、组件各生命周期的应用

3.1 getDefaultProps方法 或者 defaultProps 对象

      1.只在组件类创建的时候调用一次,之后会被缓存起来。

      2.defaultProps在组件实例之前创建,实例间共享。

      3.会和父组件设置的props进行合并。

3.2 getInitialState方法或constructor的state属性

      项目中会把组件用到的state初始化在这里。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

constructor (props) {

        super(props);

        this.state = {

            poi: null,

            activeTabId: null,

            cartCount: Shopcart.size(),

            domSize:{

                headerHeight: 100,

                bannerHeight: 200,

                categoryTabHeight: 100,

            },

            hiddenBanner: false //是否隐藏banner

        };

  

    }

 

3.3 componentWillMount()

     组件初次render之前调用,如果在此方法中调用setState,render将感知到更新后的state,并且只执行这一次render,项目中还没有用到过这个方法,属于不常用的方法。

3.4 render()

    1.组件渲染的方法,是组件唯一的必须实现的方法,在该方法中,我们可以通过props和state渲染不同的组件。返回null或者false代表不渲染任何东西。

1

2

3

4

5

6

7

8

9

10

11

render () {

        return (

            <header className="header-wrapper">

                <div className="header header-normal">

                    {this.renderLeftComponent()}

                    <span>{this.props.title || '美团商超'}</span>

                    {this.renderRightComponent()}

                </div>

            </header>

        );

    }

 

3.5 componentDidMount()

     组件装载后调用的方法,因为该方法调用的时候,组件已经装载,并且该方法不在render的循环当中,一般在该方法中做一些fetch数据或者改变state的方法。

还可以通过ReactDOM.findDOMNode(_this.refs.wrapper) 来获取DOM节点 进行操作。

1

2

3

4

5

6

7

8

9

componentDidMount() {

        this.mounted = true;

        if(this.props.poi){

            this.fetchCategoryTabs(this.props.poi.poiId);

        }

        if(!this.isCalculate) {

            this.calculateWidth(); 

        }

    }

 

3.6 componentWillReceiveProps(nextProps)

    在组件接收到新的 props 的时候调用。在初始化渲染的时候,该方法不会调用。可以在该方法中判断,当props变化时,是否再去重新fetch数据,setState。

1

2

3

4

5

componentWillReceiveProps (nextProps) {

    if(nextProps.poi &&(nextProps.poi != this.props.poi)) {

        this.fetchBannerList(nextProps.poi.poiId);

    }

}

3.7 shouldComponentUpdate(nextProps, nextState) 

     在接收到新的props或者state变化时,被调用,该方法在初始化渲染和forceUpdate的时候不会被调用。

     默认返回true,如果返回false,则render不会执行。可以在这个方法中来阻止不必要的render,因为有时是因为父组件的render引起的子组件不必要的render。

1

2

3

4

5

6

7

8

9

shouldComponentUpdate(nextProps, nextState) {

    const isStateChanged = Object.keys(nextState).some(key=> {

        return nextState[key] !== this.state[key]

    });

    const isPropsChanged = Object.keys(nextProps).some(key=> {

        return nextProps[key] !== this.props[key]

    });

    return isStateChanged || isPropsChanged

}

3.8 componentWillUpdate(nextProps, nextState) 

 

在接收到新的 props 或者 state 之前立刻调用。在初始化渲染的时候该方法不会被调用。使用该方法做一些更新之前的准备工作。不能在刚方法中使用 this.setState()。如果需要更新 state 来响应某个 prop 的改变,请使用 componentWillReceiveProps。   项目中应用不多。

 3.9 componentDidUpdate

 

在组件的更新已经同步到 DOM 中之后立刻被调用。该方法不会在初始化渲染的时候调用。使用该方法可以在组件更新之后操作 DOM 元素。

有些操作可能需要操作DOM元素,并且在第一次componentDidMount时还没有达到条件,所以需要在componentDidUpdate时再做操作,但是componentDidUpdate在render的循环函数中,

所以需要设置变量做控制。 下面例子中 this.isCalculate 就是判断是否计算过的变量。

 

 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

componentDidMount() {

    this.mounted = true;

    if(this.props.poi){

        this.fetchCategoryTabs(this.props.poi.poiId);

    }

    if(!this.isCalculate) {

        this.calculateWidth(); 

    }

}

componentDidUpdate () {

    if(!this.isCalculate) {

        this.calculateWidth(); 

    }

}

calculateWidth () {

    if(this.isCalculate) {

        return;

    }

    let tablist = this.state.categoryTabs;

    if(tablist.length == 0) {

        return;

    }

    let tabsDOM = this.refs.tablist,

        childrensDOM = tabsDOM.childNodes,

        container = this.refs.tabcontainer,

        wrapper = this.refs.wrapper,

    // 横向滚动宽度

        scrollwidth = 5;

    for(let i=0; i<childrensDOM.length; i++){

        let childDOM = childrensDOM[i];

        scrollwidth += childDOM.clientWidth + parseInt(childDOM.style.marginRight);

    }

    scrollwidth = Math.max(tabsDOM.clientWidth,scrollwidth);

    this.setState({tabsWidth: scrollwidth + 'px'});

     

    this.props.setCategoryTabHeight(wrapper.offsetHeight);

    this.isCalculate = true;

}

3.10 componentWillUnmount

在组件从 DOM 中移除的时候立刻被调用。在该方法中执行任何必要的清理,比如无效的定时器,或者清除在 componentDidMount 中创建的 DOM 元素。

可以记录组件的mount状态,在 componentDidMount 中设置this.mounted = true 。 在componentWillUnmount 中设置 this.mounted = false。

posted @ 2016-01-25 14:44  杨博客  阅读(621)  评论(0编辑  收藏  举报