组件(Components)
容许您将UI拆分为独立的可重用的部分,并单独的考虑每一个部分。javascript
React.Component
是一个抽象基类。这意味着直接引用React.Component
是毫无心义的。你能够实现一个它的子类,而且至少定义一个render()
方法便可使用。java
你可使用ES6中class
定义一个React组件:ajax
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</hr>;
}
}
若是你尚未使用ES6,你可使用React.createClass()
。编程
每一个组件都有几个『生命周期方法』,您能够重写这些方法,已便在React执行过程当中的指定时间运行本身的代码。前缀为Will
的生命周期方法会在在一些事情发生以前被调用,带有Did
前缀的方法在某些事情发生以后被调用。浏览器
当建立组件的实例并将其插入DOM时,会依次调用这些方法:服务器
constructor()
网络
componentWillMount()
函数式编程
render()
函数
componentDidMount()
性能
更新能够由prop或者state的改变引发。在从新渲染组件时依次调用这些方法:
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
当从DOM中删除组件时,将调用此方法:
componentWillUnmount()
每一个组件还提供了一些其余API:
setState()
forceUpdate()
defaultProps
displayName
propTypes
props
state
render() {
// return React Elements
}
注意:render()
方法是必须写的。
当这个方法被调用时,它会检测this.props
和this.state
并返回一个React元素。此元素能够是本地DOM组件的形式,例如<div/>
,也能够是您本身定义的一个复合组件。
你也能够返回null
或false
来表示你不想作任何渲染操做。当返回null
或false
时,ReactDOM.findDOMNode(this)
将返回null
。
render()
方法应该是纯的(pure function
,见函数式编程),这意味着它并不会修改组件state,每次调用它时都会返回相同的结果,它不会直接与浏览器交互。若是您须要与浏览器直接交互,请改用componentDidMount()
方法或者其余生命周期方法来执行你的逻辑。保持render()
的纯
可让组件更容易去思考本身应该作什么。
提示
若是shouldComponentUpdate()
返回false
,那么render()
不会被执行。
constructor(props)
在装载组件(mounting)以前调用会React组件的构造函数。当实现React.Component
子类的构造函数时,应该在任何其余语句以前调用super(props)
。不然,this.props
将在构造函数中未定义,这可能致使错误。
构造函数是初始化state的标准位置。若是不初始化state,而且不绑定组件内部方法的this指向,则不须要为React组件实现构造函数。
若是你知道你在作什么的话,你能够根据props来初始化state。这里有一个有效的React.Component
子类构造函数的例子:
constructor(props) {
super(props);
this.state = {
color: props.initialColor
};
}
注意这种模式,由于它会将props复制一份在state中,这就可能致使一个意外的bug。因此不该该将props复制到state中。相反,你须要使用提高state
的技巧,该技巧咱们在前面的文章提到过。
若是你使用props复制到state中,你还须要实现componentWillReceiveProps(nextProps)
来保持state是最新的。这个时候使用提高state的方法反而会更容易,也能产生更少的bug。
componentWillMount()
componentWillMount()
是在装载(mounting)发生以前被调用。它在render()
以前调用,因此在此方法中的设置state不会形成从新渲染。另外,应该避免在此方法中引入有任何反作用的东西(见函数式编程)
。
在服务器渲染上这是惟一一个调用的生命周期钩子函数。通常来讲,咱们建议使用constructor()
。
componentDidMount()
componentDidMount()
在组件装载到DOM后当即调用。若是须要进行DOM节点的初始化则应该在这里来执行该逻辑。若是须要从远程端点加载数据(ajax
),那么这是处理网络请求的最好地方。在此方法中设置state会去从新渲染DOM。
componentWillReceiveProps(nextProps)
componentWillReceiveProps()
在安装好的组件接收新props以前被调用。 若是你须要更新state用来响应props的更改(例如,重置它),你能够在此方法中比较this.props
和nextProps
并使用this.setState()
来替换并重置state。
注意,即便props没有改变,React
也能够调用这个方法,所以若是你只想处理props改变的状况,请确保比较当前值和下一个值是否不一样。 当父组件引发你的组件从新渲染时,就有可能会发生这种状况。
若是你只是调用this.setState()
,那么componentWillReceiveProps()
不会被调用。
shouldComponentUpdate(nextProps, netState)
使用shouldComponentUpdate()
让React知道组件是否受当前state或props变化的影响。 默认行为是在每次state更改时都会去从新渲染DOM,在绝大多数状况下,你应该依赖于这个默认行为。
当接收到新的props或state时,shouldComponentUpdate()
在渲染以前被调用。 默认为true
对于初始渲染或使用forceUpdate()
,不调用此方法。
返回false
不会阻止子组件在state更改时从新渲染。
目前,若是shouldComponentUpdate()
返回false
,那么将不会调用componentWillUpdate()
,render()
和componentDidUpdate()
。 注意,在未来React能够将shouldComponentUpdate()
做为提示而不是严格的操做指令
,返回false
仍然可能致使组件的从新渲染。
若是你肯定某些组件在某些操做时有点缓慢,你可让它继承React.PureComponent
,而不是继承React.Component
。
React.PureComponent
实现了props
和state
进行浅比较的shouldComponentUpdate()
方法。 若是你肯定想人肉处理这个浅比较
操做,你能够本身在这个函数中比较this.props
和nextProps
、this.state
和nextState
是否相同。相同返回false
,不一样返回true
,那么React就会根据返回值来确认是否跳过本次DOM渲染。
componentWillUpdate(nextProps, nextState)
当组件在收到新的props或state时,componentWillUpdate()
在渲染以前会当即调用这个方法。 使用这个方法来判断是非须要从新渲染DOM。 第一次渲染DOM不调用此方法。
注意,this.setState()
不会调用此方法。 若是你须要根据state和props来进行从新渲染DOM,请改用componentWillReceiveProps()
。
note
若是shouldComponentUpdate()
返回false
,则不会调用componentWillUpdate()
。
componentDidUpdate(prevProps, prevState)
componentDidUpdate()
在从新渲染DOM以后被调用。 第一次渲染不调用此方法。
当组件已经从新渲染后,此方法是一个执行DOM操做的好机会,同时也是一个处理网络请求的好地方,前提是你须要比较当前props与以前的props是否相同(例如,若是props没有改变,那么可能不须要进行网络请求)。
note
若是shouldComponentUpdate()
返回false
,则不会调用componentDidUpdate()
。
componentWillUnmount()
componentWillUnmount()
在组件被卸载和销毁以前当即被调用。 此方法能够执行任何有必要的清理工做,例如清理计时器,取消网络请求或清理在componentDidMount()
中建立的DOM元素。
setState(nextState, callback)
将nextState和当前state进行浅合并。 这是用于从事件处理函数和服务器请求回调中触发UI从新渲染的主要方法。
第一个参数能够是一个对象(包含一个或多个要更新的state属性),也能够是返回将要引发从新渲染的对象(state和props)。
这里有一个简单的用法:
this.setState({myKey: 'my new value'});
它也能够传入一个带有参数的函数function(state,props)=> newState
。 例如,假设咱们想要当前state中的myInteger加上props.step:
this.setState(prevState, props) => {
return {myInteger: prevState.myInteger + props.step};
}
第二种参数是回调函数,一旦setState完成而且组件被从新渲染,它就会被执行。 一般咱们建议使用componentDidUpdate()
代替这样的逻辑。
setState()
不会当即改变this.state
,但会建立并挂起state的修改。 因此在调用此方法中访问this.state
可能会返回现有值。
不能保证对setState
的因此调用都是同步操做,由于这样作是为了将屡次state修改合并为一次以便提升性能。
setState()
总会从新渲染DOM,除非shouldComponentUpdate()
回false。 若是你正在使用可突变对象,而且没法在shouldComponentUpdate()
实现条件渲染逻辑,则只有当新state与先前state不一样时调用setState()
才能避免没必要要的从新渲染。
component.forceUpdate(callback)
默认状况下,当组件的state或props改变时,组件将从新渲染。 若是你的render()
方法依赖于一些其余数据,你能够告诉React组件须要经过调用forceUpdate()
来从新渲染。
调用forceUpdate()
会致使在组件上调用render()
,跳过shouldComponentUpdate()
这将触发子组件的正常生命周期方法,包括每一个子组件的shouldComponentUpdate()
方法。 若是标记更改,React仍将更新DOM。
一般你应该尽可能避免forceUpdate()
的全部使用,而且只能从render()
中的this.props
和this.state
中读取。
defaultProps
是类组件自己的属性,用来设置类组件的默认props。 能够用来给未传入值的props设置默认值。 例如:
class CustomButton extends React.Component {
// ...
}
CustomButton.defaultProps = {
color: 'blue';
}
若是props.color
没有定义,就是将它设置为默认值blue
:
render() {
return <CustomButton />; // props.color will be set to blue
}
若是props.color
被设置为null
,那么它将会被从新赋值为null:
render() {
return <CustomButton color={null} />; // props.color will remain null
}
displayName
字符串用于调试消息。 JSX
自动设置此值;
propTypes
也是类组件自己上的一个属性,用来规范props应该是什么类型。 它是从props的名称到React.PropTypes
中定义的类型的映射。 在开发模式下,当为prop设置一个不是指定格式的无效值时,会在JavaScript控制台中显示警告信息。 在生产模式下,为了提升效率,不会进行propTypes
检查。
例如,此代码确保颜色prop是一个字符串:
class CustomButton extends React.Component {
// ...
}
CustomButton.propTypes = {
color: React.PropTypes.string
};
咱们建议尽量使用Flow
,以便在编译时进行类型检查,而不是在运行时进行类型检查。 Flow
在React中内置支持,所以能够轻松地在React应用程序上运行静态分析。
// @flow
function foo(x) {
return x * 10;
}
foo('Hello, world!');
// @flow
function bar(x): string {
return x.length;
}
bar('Hello, world!');
this.props
包含由此组件的调用者定义的props
。
特别地,this.props.children
是一个特殊的props,一般由JSX表达式中的子标签而不是标签自己定义。
state包含特定于此组件的数据,可能随时间更改。 state是用户定义的,它应该是纯JavaScript对象。
若是你不在render()
中使用它,它不该该设置state。 例如,您能够将定时器ID直接放在实例上。
永远不要直接改变this.state
,由于调用setState()
以后能够替换你所作的各类变化, 一般应该把this.state
看做是不可变的。