上篇博文使用React开发的一些注意要点对React开发的一些重点进行了简单的罗列总结,虽然也提到了React生命周期,但只略微小结,在此单独写篇React生命周期的总结。

在组件的整个生命周期中,随着该组件的props或者state发生改变,其DOM表现也会有相应的变化。一个组件就是一个状态机,对于特定地输入,它总返回一致的输出。

一个React组件的生命周期分为三个部分:初始化(实例化)、存在期和销毁时。下图详细列述了 React 组件在整个生命周期中所涉及的方法和行为:

实例化

当组件在客户端被实例化,第一次被创建时,以下方法依次被调用:

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

当组件在服务端被实例化,首次被创建时,以下方法依次被调用:

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

componentDidMount 不会在服务端被渲染的过程中调用。

getDefaultProps

对于每个组件实例来讲,这个方法只会调用一次,该组件类的所有后续应用,getDefaultPops 将不会再被调用,其返回的对象可以用于设置默认的 props(properties的缩写) 值。

var MyTitle = React.createClass({
getDefaultProps : function () {
return {
title : 'Hello World'
};
}, render: function() {
return <h1> {this.props.title} </h1>;
}
}); ReactDOM.render(
<MyTitle />,
document.body
);

React通过 propTypes 提供了一种验证 props 的方式,propTypes 是一个配置对象,用于定义属性类型:

var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
}, render: function() {
return <h1> {this.props.title} </h1>;
}
});

上面的Mytitle组件有一个title属性。PropTypes 告诉 React,这个 title 属性是必须的,而且它的值必须是字符串。现在,我们设置 title 属性的值是一个数值。

var data = 123;

ReactDOM.render(
<MyTitle title={data} />,
document.body
);

这样一来,title属性就通不过验证了。控制台会显示一行错误信息。

Warning: Failed propType: Invalid prop `title` of type `number` supplied to `MyTitle`, expected `string`.

常用的 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!');
}
}

常用的PropTypes

getInitialState

对于组件的每个实例来说,这个方法的调用有且只有一次,用来初始化每个实例的 state,在这个方法里,可以访问组件的 props。每一个React组件都有自己的 state,其与 props 的区别在于 state只存在组件的内部,props 在所有实例中共享。

getInitialState 和 getDefaultPops 的调用是有区别的,getDefaultPops 是对于组件类来说只调用一次,后续该类的应用都不会被调用,而 getInitialState 是对于每个组件实例来讲都会调用,并且只调一次。

var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function(event) {
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

但是不要直接修改 this.state,要通过 this.setState 方法来修改。

componentWillMount

该方法在首次渲染之前调用,也是再 render 方法调用之前修改 state 的最后一次机会。

render

该方法会创建一个虚拟DOM,用来表示组件的输出。对于一个组件来讲,render方法是唯一一个必需的方法。render方法需要满足下面几点:

  1. 只能通过 this.props 和 this.state 访问数据(不能修改)
  2. 可以返回 null,false 或者任何React组件
  3. 只能出现一个顶级组件,不能返回一组元素
  4. 不能改变组件的状态
  5. 不能修改DOM的输出

render方法返回的结果并不是真正的DOM元素,而是一个虚拟的表现,类似于一个DOM tree的结构的对象。react之所以效率高,就是这个原因。

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 插入文档以后,才能使用这个属性,否则会报错。

存在期

此时组件已经渲染好并且用户可以与它进行交互,比如鼠标点击,手指点按,或者其它的一些事件,导致应用状态的改变,你将会看到下面的方法依次被调用

1、componentWillReceiveProps
2、shouldComponentUpdate
3、componentWillUpdate
4、render
5、componentDidUpdate

componentWillReceiveProps

组件的 props 属性可以通过父组件来更改,这时,componentWillReceiveProps 将来被调用。可以在这个方法里更新 state,以触发 render 方法重新渲染组件。

componentWillReceiveProps: function(nextProps){
if(nextProps.checked !== undefined){ // 这里checked是从父组件传来的
this.setState({
checked: nextProps.checked
})
}
}
shouldComponentUpdate

如果你确定组件的 props 或者 state 的改变不需要重新渲染,可以通过在这个方法里通过返回 false 来阻止组件的重新渲染,返回 `false 则不会执行 render 以及后面的 componentWillUpdate,componentDidUpdate 方法。

该方法是非必须的,并且大多数情况下没有在开发中使用。

shouldComponentUpdate: function(nextProps, nextState){
return this.state.checked === nextState.checked;
//return false 则不更新组件
}
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

反模式

在 getInitialState 方法中,尝试通过 this.props 来创建 state 的做法是一种反模式。

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

经过计算后的值不应该赋给 state,正确的模式应该是在渲染时计算这些值。这样保证了计算后的值永远不会与派生出它的 props 值不同步。

//正确模式
getDefaultProps: function(){
return {
data: new Date()
}
},
render: function(){
var day = this.props.date - new Date();
return <div>Day:{day}</div>
}

如果只是简单的初始化 state,那么应用反模式是没有问题的。

深入React组件生命周期的更多相关文章

  1. React组件生命周期小结

    React组件生命周期小结 下面所写的,只适合前端的React.(React也支持后端渲染,而且和前端有点小区别,不过我没用过.) 相关函数 简单地说,React Component通过其定义的几个函 ...

  2. React—组件生命周期详解

    React—组件生命周期详解 转自 明明的博客  http://blog.csdn.net/slandove/article/details/50748473 (非原创) 版权声明:转载请注明出处,欢 ...

  3. 1.4 React 组件生命周期

    1.4.1 组件 React 中组件有自己的生命周期方法,简单理解可以为组件从 出生(实例化) -> 激活 -> 销毁 生命周期 hook.通过这些 hook 方法可以自定义组件的特性. ...

  4. 野心勃勃的React组件生命周期

    当你还在写着Angular指令,过滤器,注入,服务,提供者,视图模版的时候,是不是觉得很烦,好在这个时候,React已经神一样的出现在历史舞台. React组件    React实现了UI=Fn(St ...

  5. React组件生命周期过程说明

    来自kiinlam github94 实例化 首次实例化 getDefaultProps getInitialState componentWillMount render componentDidM ...

  6. React组件生命周期过程说明【转】

    实例化 首次实例化 getDefaultProps getInitialState componentWillMount render componentDidMount 实例化完成后的更新 getI ...

  7. 3. React 组件生命周期介绍

            React 中的每个组件都有三个阶段,这三个阶段构成了组件完整的生命周期.组件的生命周期为]); return; } this.setState({name: event.target ...

  8. react组件生命周期过程

    实例化 首次实例化 getDefaultProps getInitialState componentWillMount render componentDidMount 实例化完成后的更新 getI ...

  9. react组件生命周期

    1. Mounting/组建挂载相关 (1)componentWillMount 组件将要挂载.在render之前执行,但仅执行一次,即使多次重复渲染该组件或者改变了组件的state (2)compo ...

随机推荐

  1. Linux驱动技术(一) _内存申请

    先上基础,下图是Linux的内存映射模型,其中体现了Linux内存映射的几个特点: 每一个进程都有自己的进程空间,进程空间的0-3G是用户空间,3G-4G是内核空间 每个进程的用户空间不在同一个物理内 ...

  2. Raspberry树莓派学习笔记2—配置RobotFramework自动化测试环境

    一般RobotFramework都是安装在Windows/Linux的PC机上,这里将简单介绍在树莓派硬件平台上配置RobotFramework的开发和运行环境. 树莓派上配置了自动化测试软件,可以考 ...

  3. JS中函数参数和函数返回值的理解

    函数本质就是功能的集合 JS中函数是对象,因此,函数名实际上仅仅是一个指向函数对象的指针,不会与某个函数绑定,所以,JS中没有重载(重载就是通过传递不同类型的参数,使两个相同函数名的函数执行不同的功能 ...

  4. ROM与RAM知识

    “ROM”和“RAM”的意思: “ROM”:N年前代表一种只能写入和读取,而不能改写和擦除的设备,可以用光驱CD-ROM来说明这个道理.目前的“ROM”已经不是这个道理了,它的技术已经飞快的发展到现在 ...

  5. 【转载】简析TCP的三次握手与四次分手

    最近在补习HTTP协议相关知识点,看到这篇讲得不错,所以转载收藏一下,同时也分享给大家.原文地址:http://www.jellythink.com/archives/705,版权归原作者所有. TC ...

  6. 使用EntityFramework中DbSet.Set(Type entityType)方法碰到的问题

    使用的是EntityFramework, Version=6.0.0.0,项目原本直接使用将EntityFramework的Entity拿到UI使用,后面想使用dto对象将数据库的Entity与前台分 ...

  7. 【前端】:jQuery实例

    前言: 今天2月最后一天,写一篇jQuery的几个实例,算是之前前端知识的应用.写完这篇博客会做一个登陆界面+后台管理(i try...) 一.菜单实例 最开始的界面: 点击菜单三后的界面: < ...

  8. mfc---CFileDialog的过滤器

    CFileDialog的过滤器每种类型由两部分组成“tda|*.tda”,两种类型之间用“|”隔开

  9. C#的数据类型、数据类型的转化

    一.c#有15个预定义类型,其中13个是值类型,两个是引用类型(string 和 object)这里主要说明整型.浮点型.布尔型以及引用型 1.整型数据 2.浮点型 浮点型从精度有低到高有float. ...

  10. BOM基础(一)

    学完了js的基础语法和DOM之后,就要要看看javascript中最后一项BOM了.BOM,全称brower document model,翻译过来就是浏览器对象模型.DOM是文档对象模型,属于BOM ...