标签来处理当前的差异检查逻辑。当返回null或者false的时候this.getDOMNode()将返回null。render()函数应该是纯粹的,也就是说该函数不修改组件state,每次调用都返回相同的结果,不读写DOM信息,也不和浏览器交互(例如通过使用setTimeout)。如果需要和浏览器交互,在componentDidMount()中或者其它生命周期方法中做这件事。保持render()纯粹,可以使服务器端渲染更加切实可行,也使组件更容易被理解。
propTypes
函数原型 object propTypes propTypes
是React提供的一种验证机制,该对象中定义了一系列的验证方法,可对props
进行验证。组件初始化时,如果传递的props
属性和propTypes
不匹配,则会打印一个console.warn
日志。
React.createClass({
propTypes: {
// 验证布尔值
optionalBool: React.PropTypes.bool,
// 验证是一个函数
optionalFunc: React.PropTypes.func,
// 验证是数字
optionalNumber: React.PropTypes.number,
// 自定义验证器,验证失败需要返回一个 Error 对象。不要直接
// 使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。
customProp: function (props, propName, componentName) {
// 自定义的验证方法 ……
} ,
// 其它验证 ……
},
/* 其它specification... */
});
propTypes使用示例:
var App = React.createClass({
propTypes: {
site: React.PropTypes.shape({
domain: React.PropTypes.string.isRequired,
name: React.PropTypes.string
}).isRequired
},
render: function () {
return (
站点信息-{this .props.site.name}:{this .props.site.domain}
);
}
});
var site = {
name: 4, // 不合法的类型
domain: 'itbilu.com'
}
ReactDOM.render( , document.getElementById('example')); // 运行后会抛出以下错误
// Warning: Failed propType: Invalid prop `site.name` of type `number` supplied to `App`, expected `string`.
mixins
函数原型 array mixins mixin 数组允许使用混合来在多个组件之间共享行为。如一个组件需要定期更新,这时我们可以setInterval()
方法很容易的做到,但当不需要它时,我们要取消定时器以节省内存。下面我们使用 React 提供的生命周期方法来通知组件创建或销毁,并结合mixin
,实现组件的定时清理:
var SetIntervalMixin = {
componentWillMount: function () {
this .intervals = [];
},
setInterval: function () {
this .intervals.push(setInterval.apply(null , arguments));
},
componentWillUnmount: function () {
this .intervals.map(clearInterval);
}
});
var TickTock = React.createClass({
mixins: [SetIntervalMixin], // 引用 mixin
getInitialState: function () {
return {seconds: 0};
},
componentDidMount: function () {
this .setInterval(this .tick, 1000); // 调用 mixin 的方法
},
tick: function () {
this .setState({seconds: this .state.seconds + 1});
},
render: function () {
return (
React 已经运行了 {this .state.seconds} 秒。
);
}
});
React.render( , document.getElementById('example'));
statics
函数原型 object statics
statics对象允许你定义静态的方法,这些静态的方法可以在组件类上调用。例如:
var MyComponent = React.createClass({
statics: {
customMethod: function (foo) {
return foo === 'bar';
}
},
render: function () {
}
});
MyComponent.customMethod( 'bar'); // true
在这块定义的方法都是静态的,意味着你可以在任何组件实例创建之前调用它们,这些方法不能获取组件的props和state。如果你想在静态方法中检查props的值,在调用处把props作为参数传入到静态方法。
displayName
函数原型 string displayName displayName 描述插件的显示名称。JSX自动设置该值。
var App = React.createClass({
displayName: 'App',
render: function () {
return (
itbilu.com
)
}
});
React组件生命周期
所谓生命周期,就是一个对象从开始生成到最后消亡所经历的状态某个确定的时间点执行的方法,理解生命周期,是合理开发的关键。通过反复试验,得到了组件的生命周期在不同状态下的执行顺序:
1.当首次装载组件时: 按顺序执行 getDefaultProps、getInitialState、componentWillMount、render 和 componentDidMount; 2.当重新装载组件时, 此时按顺序执行 getInitialState、componentWillMount、render 和componentDidMount,并不执 行getDefaultProps 3.当再次渲染组件时,组件接受到新的Props,此时按顺序执行componentWillReceiveProps、shouldComponentUpdate、 componentWillUpdate、render 和componentDidUpdate。
4.当再次渲染组件时,组件接受到新的state,此时按顺序执行shouldComponentUpdate、componentWillUpdate、render 和componentDidUpdate。
4.当组件卸载时: 执行componentWillUnmount
如图,可以把组件生命周期大致分为三个阶段:
第一阶段:是组件第一次绘制阶段,如图中的上面虚线框内,在这里完成了组件的加载和初始化; 第二阶段:是组件在运行和交互阶段,如图中左下角虚线框,这个阶段组件可以处理用户交互,或者接收事件更新界面; 第三阶段:是组件卸载消亡的阶段,如图中右下角的虚线框中,这里做一些组件的清理工作。 下图对每种情况做了更清晰明了的说明
生命周期回调函数
下面来详细介绍生命周期中的各回调函数。
getDefaultProps 其原型如下: object getDefaultProps(); 在组件类创建的时候调用一次,然后返回值被缓存下来。如果父组件没有指定 props 中的某个键,则此处返回的对象中的相应属性将会合并到this.props(
使用in
检测属性).该方法在任何实例创建之前调用,因此不能依赖于this.props
。另外,getDefaultProps()
返回的任何复杂对象将会在实例间共享,而不是每个实例拥有一份拷贝。
getInitialState 其原型如下: object getInitialState() 在组件挂载之前调用一次。返回值将会作为 this.state
的初始值。
componentWillMount
然后,准备加载组件,会调用 componentWillMount(),其原型如下: void componentWillMount() 这个函数调用时机是在组件创建,并初始化了状态之后,在第一次绘制 render() 之前。可以在这里做一些业务初始化操作,也可以设置组件状态。这个函数在整个生命周期中只被调用一次。
componentDidMount 在组件第一次绘制之后,会调用 componentDidMount(),函数原型如下: void componentDidMount() 通知组件已经加载完成。这个函数调用的时候,真实DOM已经构建完成,你可以在这个函数开始获取其中的元素或者子组件了。需要注意的是,React框架是先调用子组件的 componentDidMount(),然后调用父组件的componentDidMount函数。从这个函数开始,HTML就可以和JS交互了,例如设置计时setTimeout或者setInterval,或者发起网络请求。这个函数也是只被调用一次。这个函数之后,就进入了稳定运行状态,等待事件触发。
componentWillReceiveProps
如果组件收到新的属性(props),就会调用 componentWillReceiveProps(),其原型如下:
void componentWillReceiveProps(object nextProps)
输入参数 nextProps 是即将被设置的属性,旧的属性还是可以通过 this.props 来获取。在这个回调函数里面,你可以根据属性的变化,通过调用 this.setState() 来更新你的组件状态,这里调用更新状态是安全的,并不会触发额外的 render() 调用。如下:
componentWillReceiveProps:function(nextProps) { this.setState({ likesIncreasing: nextProps.likeCount >this.props.likeCount }); }
shouldComponentUpdate
当组件接收到新的属性和状态改变的话,都会触发调用 shouldComponentUpdate(...),函数原型如下:
boolean shouldComponentUpdate(object nextProps, object nextState)
输入参数nextProps和上面的componentWillReceiveProps函数一样,nextState表示组件即将更新的状态值。这个函数的返回值决定是否需要更新组件,如果true表示需要更新,继续走后面的更新流程。否者,则不更新,直接进入等待状态。默认情况下,这个函数永远返回true用来保证数据变化的时候UI能够同步更新。在大型项目中,你可以自己重载这个函数,通过检查变化前后属性和状态,来决定UI是否需要更新,能有效提高应用性能。 componentWillUpdate
如果组件状态或者属性改变,并且上面的shouldComponentUpdate返回为true,就会开始准更新组件,并调用componentWillUpdate(),其函数原型如下:
void componentWillUpdate(object nextProps, object nextState)
输入参数与shouldComponentUpdate一样,在这个回调中,可以做一些在更新界面之前要做的事情。需要特别注意的是,在这个函数里面,你就不能使用this.setState来修改状态。这个函数调用之后,就会把nextProps和nextState分别设置到this.props和this.state中。紧接着这个函数,就会调用render()来更新界面了。
componentDidUpdate 调用了render()更新完成界面之后,会调用componentDidUpdate()来得到通知,其函数原型如下:
void componentDidUpdate(object prevProps, object prevState)
因为到这里已经完成了属性和状态的更新了,此函数的输入参数变成了prevProps和prevState。
componentWillUnmount
当组件要被从界面上移除的时候,就会调用componentWillUnmount(),其函数原型如下: void componentWillUnmount() 在这个函数中,可以做一些组件相关的清理工作,例如取消计时器、网络请求等。 总结: 1.react组件的方法和属性
组件的参数
渲染组件 :render
调试输出 :displayName
跨组件共享 :mixins
验证对象 :propTypes
静态方法对象 :statics
组件生命周期
创建期 :getDefaultProps
创建期 :getInitialState
创建期 :componentWillMount
创建期 :componentDidMount
存在期 :componentWillReceiveProps
存在期 :shouldComponentUpdate
存在期 :componentWillUpdate
存在期 :componentDidUpdate
销毁&清理期 :componentWillUnmount
2.编程建议
1. 不建议在 getDefaultProps 、 getInitialState 、 shouldComponentUpdate 、 componentWillUpdate 、 render, componentWillUnmount 中调用setState,特别注意:不能在shouldComponentUpdate 和 componentWillUpdate 中调用setState,因为更新 state 会导致组件更新进而调用shouldComponentUpdate 和 componentWillUpdate 方法,在shouldComponentUpdate 和 componentWillUpdate 中更新了state,又会导致组件更新而调用shouldComponentUpdate 和 componentWillUpdate 方法,简而言之,会导致循环调用。
2.除了需要操作DOM的初始化操作放在componentDidMount中,其余的初始化操作应全部丢到componentWillMount中进行,特别是涉及修改state 的操作。因为这些方法如果丢到componentDidMount中,会导致组件加载完成后立刻检测到state变更,触发组件再次更新,影响页面性能。
3.不要在getDefaultProps中进行任何针对实例的操作。该方法在任何实例创建前调用,在该方法中访问不到任何实例。
4.一定要在componentWillUnmount中做好清理工作,否则你会面临一大堆不可预测且难以调试的 bug。