前言
React的主要思想是通过构建可复用组件来构建页面.
所谓组件,其实就是有限状态机(FSM),通过状态渲染对应的界面,且每个组件都有自己的生命周期,
它规定了组件的状态和方法需要在哪个阶段改变和执行.
class Collections extends Component {
constructor(props) {
super(props);
this.state = {
a: 1
}
}
add = () => {
this.setState({
a: this.state.a + 1
});
}
componentWillMount() {
console.log('componentWillMount');
}
componentDidMount() {
console.log('componentDidMount');
this.setState({
a: 2
});
}
componentWillUnMount() {
console.log('componentWillUnMount');
}
render() {
console.log('render');
return (
<div className="collections">
{ this.state.a }
<Example a={ this.state.a } />
<button onClick={ this.add }>btn</button>
</div>
);
}
}
import React, { Component, PropTypes } from 'react';
export default class Example extends Component {
static propTypes = {
a: PropTypes.number.isRequired
};
static defaultProps = {
a: 0
};
constructor(props) {
super(props);
this.state = {
b: 1
};
}
add = () => {
this.setState({
b: this.state.b + 1
});
}
componentWillReceiveProps(nextProps) {
console.log(nextProps);
if (nextProps.a === 4) {
this.setState({
b: 1000
});
}
}
shouldComponentUpdate(nextProps, nextState) {
console.log(nextProps);
console.log(nextState);
if (nextState.b === 4) {
return false;
}
return true;
}
componentWillMount() {
console.log('子组件componentWillMount');
}
componentDidMount() {
console.log('子组件componentDidMount');
}
render() {
console.log('子组件render');
return (
<div>
<p>a:{ this.props.a }</p>
<p>b:{ this.state.b }</p>
<button onClick={ this.add }>子组件add</button>
</div>
);
}
}
初探react生命周期
当首次挂载组件时,按顺序执行getDefaultProps,getInitialState,componentWillMount,render,componentDidMount
当卸载组件时,执行componentWillUnMount
当再次渲染组件时,组件接收到更新状态,此时按顺序执行componentWillReceiveProps,shouldComponentUpdate,
componentWillUpdate,render和componentDidUpdate
使用createClass创建自定义组件
createClass是创建自定义组件的入口方法,负责管理生命周期方法中的getDefaultProps.
该方法在整个生命周期中只执行一次,这样所有实例初始化的props将会被共享.
通过createClass创建自定义组件,利用原型继承ReactClassComponent父类,
按顺序合并minin,设置初始化defaultProps,返回构造函数.
当使用ES6 classes编写React组件时,class MyComponent extends React.Component
其实就是调用内部方法createClass创建组件.
var ReactClass = {
// 创建自定义组件
createClass: function(spec) {
var Constructor = function(props, context, updater) {
// /自动绑定
if (this._reactAutoBindPairs.length) {
bindAutoBindMethods(this);
}
this.props = props;
this.context = context;
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
this.state = null;
// ReactClass没有构造函数,通过getInitialState和componentWillMount来代替
var initialState = this.getInitialState ? this.getInitialState() : null;
this.state = initialState;
};
// 原型继承父类
Constructor.prototype = new ReactClassComponent();
Constructor.prototype.constructor = constructor;
Constructor.prototype._reactAutoBindPairs = [];
// 合并mixin
injectedMixins.forEach(
minSpecIntoComponent.bind(null, Constructor)
);
minSpecIntoComponent(Constructor, spec);
// 所有mixin合并后初始化defaultProps(在整个生命周期中,getDefaultProps只执行一次)
if (Constructor.getDefaultProps) {
Constructor.defaultProps = Constructor.getDefaultProps();
}
// 减少查找并设置原型的时间
for (var methodName in ReactClassInterface) {
if (!Constructor.prototype[methodName]) {
Constructor.prototype[methodName] = null;
}
}
return Constructor;
}
};
MOUNTING
mountComponent负责管理生命周期中的getInitialState,componentWillMount,render和componentDidMount
由于getDefaultProps是通过构造函数进行管理的,所以也是整个生命周期中最先开始执行的.
react是利用更新队列this._pendingStateQueue以及更新状态this._pendingReplaceState
和this._pendingForceUpdate来实现setState的异步更新机制.
其实,mountComponent本质上是通过递归渲染内容的,由于递归的特性,父组件的componentWillMount
在其子组件的componentWillMount之前调用,而父组件的componentDidMount在其子组件的componentDidMount之后调用.
RECEIVE_PROPS
updateComponent负责管理生命周期中的componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,
render和componentDidUpdate.
若存在componentWillReceiveProps,则执行.
如果此时在componentWillReceiveProps中调用setState,是不会触发re-render的,而是会进行state合并.
且在componentWillReceiveProps,shouldComponentUpdate和componentWillUpdate中也还是无法获取到更新后的this.state,
即此时访问的this.state仍然是未更新的数据,因此只有render和componentDidUpdate中才能获取到更新后的this.state
componentWillReceiveProps(nextProps) {
console.log(nextProps);
if (nextProps.a === 4) {
this.setState({
b: 1000
}, () => {
console.log(this.state.b);
});
}
}
UNMOUTING
unmountComponnet负责管理生命周期中的componentWillUnMount
如果存在componentWillUnMount,则执行并重置所有相关参数,更新队列以及更新状态,
如果此时在componentWillUpdate中调用setState,是不会触发re-render的,这是因为
所有更新队列和更新状态都被重置为null,并清除了公共类,完成了组件卸载操作.
无状态组件
无状态组件只是一个render方法,并没有组件类的实例化过程,也没有实例返回.
无状态组件没有状态,没有生命周期,只是简单的接受props渲染生成DOM结构,
是一个纯粹为渲染而生的组件.
由于无状态组件有简单,便捷,高效等诸多优点,所以如果可能的话请尽量使用无状态组件.
import React from 'react';
const HelloWorld = (props) => {
return (
<div>{ props.a }</div>
);
}
export default HelloWorld;