React.js学习笔记之组件生命周期
@(React学习)
什么是组件
React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。
组件类只能包含一个顶层标签,否则会报错。
var HelloXiaowang = React.createClass({
render: function() {
return <h1>Hello {this.props.name}</h1>;
}
});
ReactDOM.render(
<HelloXiaowang name="junyan" />,document.getElementById('shuaige')
);
上面代码中,变量 HelloXiaowang 就是一个组件类。模板插入 HelloXiaowang /> 时,会自动生成 HelloXiaowang 的一个实例(下文的"组件"都指组件类的实例)。
render
所有组件类都必须有自己的render方法,用于输出组件 ReactElement render ( )
当调用的时候,会检测 this.props 和 this.state,返回一个单子级组件。该子级组件可以是虚拟的本地 DOM 组件(比如 div /> 或者 React.DOM.div()),也可以是自定义的复合组件。
var HelloXiaowang = React.createClass({
render: function() {
return <h1>Hello {this.props.name}</h1>;
}
});
render ( ) 函数应该是纯粹的,也就是说该函数不修改组件 s
tate,每次调用都返回相同的结果,不读写 DOM 信息,也不和浏览器交互(例如通过使用 setTimeout)。如果需要和浏览器交互,在 componentDidMount() 中或者其它生命周期方法中做这件事。保持 render() 纯粹,可以使服务器端渲染更加切实可行,也使组件更容易被理解。
生命周期
组件本质上是状态机,输入确定,输出一定确定
状态机本质上是状态与转移的结合。当状态发生转换时会触发不同的钩子函数,从而让开发者有机会做出相应。 组件的声明周期分成三个状态:
初始化阶段Mounting
类创建完成之后,就可以进行实例化。
初始化阶段可以使用的函数:
getDefaultProps: 只调用一次,实例之间共享引用
getInitialState: 初始化每个实例特有的状态
componentWillMount: render 之前最后一次修改状态的机会。如果在这个方法内调用setState ,render() 将会感知到更新后的state ,将会执行仅一次,尽管state 改变了。
render: 只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出
componentDidMount: 成功render并渲染完成真实DOM之后触发,可以修改DOM
调用顺序
当组件在客户端被实例化,第一次被创建时,以下方法依次被调用:
getDefaultProps
getInitialState
componentWillMount
render
componentDidMount
当组件在服务端被实例化,首次被创建时,以下方法依次被调用:
getDefaultProps
getInitialState
componentWillMount
render
componentDidMount 不会在服务端被渲染的过程中调用。
实例
getDefaultProps方法不是在组件创建的时候调用,而是在createClass时调用。
var count = 0;
var HelloWorld = React.createClass({
getDefaultProps:function(){
return {name:"dada"};
},
getInitialState:function(){
return {
myCount:count++,ready:false
};
},
componentWillMount:function(){
this.setState({ready:true});
},
render:function(){
return <p>Hello,{this.props.name?this.props.name:"World"}
<br/>{''+this.props.ready}{this.state.myCount}</p>;
},componentDidMount:function(){
$(ReactDOM.findDOMNode(this)).append("bianke");
}
});
ReactDOM.render(<HelloWorld/>,document.getElementById('shuage'))
阮老师例子:
var Hello = React.createClass({
getInitialState: function () {
return {
opacity: 1.0
};
},componentDidMount: function () {
this.timer = setInterval(function () {
var opacity = this.state.opacity;
opacity -= .05;
if (opacity < 0.1) {
opacity = 1.0;
}
this.setState({
opacity: opacity
});
}.bind(this),100);
},render: function () {
return (
<div style={{opacity: this.state.opacity}}>
Hello {this.props.name}
</div>
);
}
});
ReactDOM.render(
<Hello name="world"/>,document.body
);
上面代码在hello组件加载以后,通过 componentDidMount 方法设置一个定时器,每隔100毫秒,就重新设置组件的透明度,从而引发重新渲染。
另外组件的style属性的设置方式要写成style={{opacity: this.state.opacity}}
React.findDOMNode()
如果这个组件已经被初始化到DOM中,这个方法返回相应的原生浏览器的DOM元素。这个方法用于读取这个DOM的值,例如表单的值与DOM的方法。在多数情况下附加一个ref 属性与DOM节点上,用来避免使用findDOMNode 。当render 返回null或false时,findDOMNode 也返回null。
注意:
运行中阶段Updating
此时组件已经渲染好并且用户可以与它进行交互,比如鼠标点击,手指点按,或者其它的一些事件,导致应用状态的改变
运行中阶段可以使用的函数
componentWillReceiveProps:父组件修改属性触发,可以修改新属性、修改状态。它是在组件发生改变之前触发
shouldComponentUpdate:返回false会阻止render调用
componentWillUpdate:不能修改属性与状态
render: 只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出
componentDidUpdate:可以修改DOM
componentWillReceiveProps
在组件接收到新的 props 的时候调用。在初始化渲染的时候,该方法不会调用。 用此函数可以作为 react 在 prop 传入之后,render() 渲染之前更新 state 的机会。老的 props 可以通过this.props 获取到。在该函数调用用this.setState() 将不会引起第二次渲染。
componentWillReceiveProps: function(nextProps) {
this.setState({
likesIncreasing: nextProps.likeCount > this.props.likeCount
});
}
对于 state,没有相似的方法:componentWillReceiveState 。将要传进来的 prop 可能会引起 state 改变,反之则不然。如果需要在 state 改变的时候执行一些操作,请使 componentWillUpdate 。
shouldComponentUpdate
在接收到新的 props 或者 state,将要渲染之前调用。该方法在初始化渲染的时候不会调用,在使用 forceUpdate 方法的时候也不会。 如果确定新的 props 和 state 不会导致组件更新,则此处应该 返回 false。
shouldComponentUpdate: function(nextProps,nextState) {
return nextProps.id !== this.props.id;
}
如果shouldComponentUpdate 返回 false,则render() 将不会执行,直到下一次 state 改变。
如果性能是个瓶颈,尤其是有几十个甚至上百个组件的时候,使用shouldComponentUpdate 可以提升应用的性能。
默认情况下shouldComponentUpdate 总会返回 true,在 state 改变的时候避免细微的 bug,但是如果总是小心地把 state 当做不可变的,在render() 中只从 props 和 state 读取值,此时你可以覆盖shouldComponentUpdate 方法,实现新老 props 和 state 的比对逻辑。
componentWillUpdate
在接收到新的 props 或者 state 之前立刻调用。在初始化渲染的时候该方法不会被调用。使用该方法做一些更新之前的准备工作。
你不能在此方法中使用this.setState() 。如果需要更新 state 来响应某个 prop 的改变,请使用componentWillReceiveProps 。
componentDidUpdate
在组件的更新已经同步到 DOM 中之后立刻被调用。该方法不会在初始化渲染的时候调用。使用该方法可以在组件更新之后操作 DOM 元素。
调用顺序
每次修改 state,都会重新渲染组件,实例化后通过 state 更新组件,会依次调用下列方法:
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
但是不要直接修改 this.state,要通过 this.setState 方法来修改。
实例
正确用法
var HelloXianrou = React.createClass({
componentWillReceiveProps:function(newProps){
console.log(newProps);
},render:function () {
console.log(4);
return <p>Hello {this.props.name||"World"}</p>
},componentDidUpdate:function () {
$(ReactD.findDOMNode(this)).append("<p>大大是大帅哥</p>")
}
});
var HelloDada = React.createClass({
getInitialState:function () {
return {name:''};
},handleChange:function (e) {
this.setState({name:e.target.value});
},render:function () {
return <div>
<HelloXianrou name={this.state.name}></HelloXianrou>
<br/>
<input type="text" onChange={this.handleChange} />
</div>
}
});
ReactDOM.render(<HelloDada></HelloDada>,document.getElementById('reactDemo'))
销毁阶段Unmounting
销毁阶段可以使用的函数
componentWillUnmount :在删除组件之前进行清理操作,比如计时器和事件监听器。或者清除在 componentDidMount 中创建的 DOM 元素。
ReactDOM.unmountComponentAtNode
移除一个已经初始化DOM过的React组件,清理它的操作和状态。如果这个组件中没有初始化过的组件,这个方法没有任何作用。如果这个组件被销毁则返回true,反之返回false
实例
var HelloXianrou = React.createClass({
render:function () {
console.log(4);
return <p>Hello {this.props.name||"World"}</p>
},componentWillUnmount:function () {
console.log("Booooooooooom!!")
}
});
var HelloDada = React.createClass({
getInitialState:function () {
return {name:''};
},handleChange:function (e) {
/* if (e.target.value == "123") {
React.unmountComponentAtNode(document.getElementById('reactDemo')[0]);
return;
} */
this.setState({name:e.target.value});
},render:function () {
/* if(this.state.name == "123"){
return <p>123</p>
} */
return <div>
<HelloXianrou name={this.state.name}></HelloXianrou>
<br/>
<input type="text" onChange={this.handleChange} />
</div>
}
});
ReactDOM.render(<HelloDada></HelloDada>,document.getElementById('reactDemo'))
小结
本文主要介绍了组件的生命周期。许多方法在组件生命周期中某个确定的时间点执行。
特别感谢
极客学院React.js系列课程
React 入门实例教程 by 阮一峰
React.js官方文档
淡忘~浅思:React组件的生命周期
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|