目次
1.react组件的两种建立写法
2.组件的生命周期在差别状况下的实行递次
3.组件各生命周期的运用
1.react组件的两种建立写法
第一种ES5写法,React.createClass
React.createClass({
getDefaultProps() {
return {
key1:value1
}
},
getInitialState() {
return {
state1:state1
}
}
});
第二种是ES6写法,继续React.Component类
export default class Test1 extends React.Component {
constructor (props) {
super(props);
this.state = {
state1: state1
}
}
static defaultProps = {
data: 2,
};
static propTypes = {
optionsData: React.PropTypes.array,
onSelect: React.PropTypes.func,
selectedOption: React.PropTypes.object,
topStyle: React.PropTypes.any,
placeholder: React.PropTypes.string
}
}
getDefaultProps、getInitialState是在createClass时挪用的要领,而在继续component类时,getDefaultProps要领对应给类增加静态属性 defaultProps ,getInitialState 对应在类的组织函数中设置 state属性
2.组件的生命周期在差别状况下的实行递次
组件首次装载(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(组件接收到新的props才会挪用,只是转变state时不挪用)→
componentWillUpdate→
render →
componentDidUpdate。
零丁挪用setState的从新衬着
componentWillUpdate→
render →
componentDidUpdate
1、在单页运用中,用react-router的history做页面跳转时,是将当前route的一切组件卸载,再跳转返来时是从新装载组件,而不是首次装载。
2、在运用react-native的Navigator时,每次push新页面的时刻是首次加载,旧页面没有卸载,在pop新页面的时刻,新页面会卸载 挪用Unmount,旧页面是从新衬着
componentWillReceiveProps→
componentWillUpdate→
render →
componentDidUpdate。
,不是从新装载,也没有从新衬着的shouldComponentUpdate掌握,所以pop返来一定从新衬着。
3、组件在内存中装载过一次以后,组件的defaultProps就初始化了,以后装载就不会从新设置。
4、父组件的render都邑引发子组件的从新衬着。
5、 不能在componentWillUpdate ,render和componentDidUpdate 中挪用setState
3.组件各生命周期的运用
3.1 getDefaultProps要领 或许 defaultProps 对象
只在组件类建立的时刻挪用一次,以后会被缓存起来。
defaultProps在组件实例之前建立,实例间同享。
会和父组件设置的props举行兼并。
3.2 getInitialState要领或constructor的state属性
项目中会把组件用到的state初始化在这里
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,能够在此要领中fetch数据,不须要dom操纵的数据猎取。
3.4 render()
组件衬着的要领,是组件唯一的必需完成的要领,在该要领中,我们能够经由过程props和state衬着差别的组件。返回null或许false代表不衬着任何东西。
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节点 举行操纵。
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。
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。
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 就是推断是不是计算过的变量。
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。