版权声明:本文为博主原创文章,未经博主允许不得转载。
PS:转载请注明出处
作者:TigerChain
地址:http://www.jianshu.com/p/e3d1ecfb6312
本文出自TigerChain简书
git 地址:https://github.com/tigerchain/react-lesson
教程简介
- 1、阅读对象
本篇教程适合初学者,老鸟直接略过,如果有误,欢迎指出,谢谢。
-
2、教程难度
初级
3、Demo 地址
https://github.com/tigerchain/react-lesson/tree/master/lesson02/11-lifecycle,如果大家喜欢,麻烦点个 star
正文
1、什么是生命周期
生命周期指的是一个对象的生老病死。当然生命周期又为广义和狭义的。具体分为以下几类。
- 1、动物的生命周期:从初生到死亡。
- 2、产品的生命周期:从开始到淘汰。(一般指提市场寿命)
- 3、语言或平台中某个组件的生命周期:比如 activity 的生命周期,指的就是 activity 的创建到销毁的过程。
- 4、其它生命周周期
2、React 的生命周期
先看 React 的生命周期图,虽然你可能不理解,通过后面的学习再回头来看这幅图,就会恍然大悟。
一、这里说的 React 的生命周期指的就是 React 组件的生命周期。React Component 通过定义几个函数来控制组件在生命周期每个阶段的功能。
总的来说 React 组件的生命周期有三种状态
1、mounting: 插入真实 DOM </br>
2、updating: 正在被重新渲染 props 或 state 改变 </br>
3、unmounting: 卸载 移除真实 DOM
在 React 中为每个状态又分别提供了两种处理函数,就是 will 和 did , will 是进入状态之前调用的, did 是进入状态之后调用的.
总的来说,三种状态对应不同的函数
- mounting 对应的函数
constructor()
componentWillMount()
render()
componentDidMount()
- updating 对应的函数
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
- unmounting 对应的函数
componentWillUnmount()
PS:一个组件中 redner() 方法是必须的。
二、和组件生命周期相关的函数有
上面笼统的说了一下和组件生命周期相关的方法,我们下面逐一来说明。
- 1、构造函数
constructor(props, context)
构造函数,在组件创建的时候调用一次。
- 2、componentWillMount()
void componentWillMount()
在组件挂载之前( render()之前 )调用。可以用于加载 Loading 条了等操作。
- 3、render
render() ;
render 方法顾名思义,就是渲染的意思,它有一个返回值,就是返回一个 React 元素(自定义组件或是呈现 DOM 组件的元素),当然如果你什么也不想返回就可以 return null 或 return false (组件就不显示了),render() 里面应该是纯净的 (不能在里面修改组件的状态,也不能在里面请求服务器等耗时操作[ componentDidMount 方法中进行耗时操作]),只是用来渲染组件。
- 4、componentDidMount()
void componentDidMount()
在组件挂载之后调用。可以用于耗时操作(请求服务器或定时器等)。
- 5、componentWillReceiveProps()
void componentWillReceiveProps(nextProps)
这里的 props 是父组件传递给子组件的。父组件发生 render 的时候就会调用子组件的 componentWillReceiveProps (不管 props 有没有更新,也不管父子组件之间有无数据交换),在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()来更新你的组件状态,旧的属性还是可以通过this.props来获取,这里调用更新状态是安全的,并不会触发额外的render调用。
- 6、shouldComponentUpdate()
bool shouldComponentUpdate(nextProps, nextState)
这个方法在组件挂载之后,当你调用 setState() 方法的时候都会调用此方法用来判断是否要重新渲染组件,如果返回 true 则需要重新渲染,如果是 false 则不会。我们可以在这个方法中处理只是数据改变,界面不改变的情况,用来优化渲染效率。
- 7、componentWillUpdate()
void componentWillUpdate(nextProps, nextState)
顾名思义,就是组件更新前被调用的方法,具体是当 props 和 state 发生改变的时候就会执行此方法并且在 redner() 方法之前进行。这个方法也在 shouldComponentUpdate() 方法返回 true 的时候就会调用,返回 false 不会调用, 使用此方法为更新前做一些准备。初始化渲染的时候不会调用这个方法。
PS:注意一点,在这个方法中不能会用 this.setState() 方法来修改状态。当这个函数调用之后,就会把 nextProps 和 nextState 分别设置到 this.props 和 this.nextState 方法中,接着就会调用 render() 方法来渲染了。
- 8、componentDidUpdate()
void componentDidUpdate()
组件渲染后就会调用 componentDidUpdate() 方法,但是首次 render() 的时候是不会调用的,首次 render() 的时候调用的是 componentDidMount() 方法。
componentWillMount()、componentDidMount 和 componentWillUpdate()、componentDidUpdate 是一一对应的,前者是在挂载的时候会被调用,但是后者是每次更新渲染之后都会调用。
- 9、componentWillUnmount()
void componentWillUnmount()
组件被卸载的时候调用,一般情况下在 componentWillUnmount() 说法中清除注册的事件,比如取消定时器,网络请求等。
3、React 中的更新方式
总的来说,在 React 中,想要 redner 有以下四种方式。
假使 shouldComponentUpdate 都是返回 true 的情况下
- 1、首次初化 render
- 2、调用 this.setState() 方法 (我们知道它是异步的,不是每调用一次 setState 都会触发一次 render ,React 有时可能会合并操作,再一次进行 render)
- 3、props 发生改变,但是一般不建议直接调用 this.setProps()
- 4、手动调用 this.forceUpdate(不推荐这样使用)
到目前为止,我们大体对 React 组件的生命周期有一个了解了,下面我们通过 Demo 来直观的感觉一下。
4、实例演示组件的生命周期
经过上面的学习,我们大体对 React 组件的生命周期有了一定的认识,下面我们写一个 Demo 来验证一下。
我们可以使用前面学过的知识使用 yarn + webpack + ES6 来创建项目,如果不懂这些知识,可以看看前面相关的章节。以下 Demo 是在 mac 环境下开发的。
1、打开命令行,新建 lifecycle 目录
mkdir lifecycle
2、进入到 lifecycle 文件夹下,并新建 public 和 app 目录。
cd lifecycle
mkdir public
mkdir app
3、分别在 app 中 和 public 中新建 index.html 和 main.js
# index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React-LifeCycle</title>
</head>
<body>
<div id="container"></div>
<script src="bundle.js"></script>
</body>
</html>
# main.js
import React from 'react' ;
import ReactDOM from 'react-dom' ;
import LifeCycle from './LifeCycle.js' ;
/**
* 定义一个父组件
*/
class Main extends React.Component{
constructor(props){
super(props) ;
this.state = {
name:'junjun'
}
}
render(){
return(
<LifeCycle
umout={this.unmoutComponent}
name={this.state.name}
testComponentWillReceiveProps={this.changeState.bind(this)}
/>
) ;
}
/**
* 卸载组件
*/
unmoutComponent(){
// 这里卸载父组件也会导致卸载子组件
ReactDOM.unmountComponentAtNode(document.getElementById("container"));
}
/**
* 通过修改 state 来修改 props 用来测试 componentWillReceiveProps 方法
*/
changeState(){
this.setState({
name:'TigerChain11111'
})
}
}
ReactDOM.render(
<Main />,
document.getElementById('container')
) ;
在这里我一口气写完了,注释非常详细,如果你学习过前面章节的知识,那么这个很容易看懂。
4、在 app 中再新建 LifeCycle.js
# LifeCycle.js
import React, { Component, PropTypes } from 'react';
/**
* 定义一个生命周期的组件
*/
export default class LifeCycle extends Component {
constructor(props) {
super(props);
console.log("~~ Initial render ~~");
console.log("~~ constructor ~~");
alert("~~ Initial render ~~") ;
alert("~~ constructor ~~") ;
this.state = {
name:'TigerChain'
}
}
/**
* 在挂载之前调用
*/
componentWillMount(){
console.log("~~ componentWillMout ~~");
alert("~~ componentWillMout ~~") ;
}
render() {
console.log("~~ render ~~");
alert("~~ render ~~") ;
return (
<div>
LifeCycle Demo <p/>
<button onClick={this._changeProps.bind(this)}>changeProps</button><p/>
<button onClick={this._setState.bind(this)}>setState</button><p/>
<button onClick={this._forceWithUpdate.bind(this)}>forceWithUpdate</button><p/>
<button onClick={this._unmout.bind(this)}>unmout</button><p/>
<button onClick={this.koukou.bind(this)}>parentChangeProps</button> <p/>
</div>);
}
/**
* 测试 ComponentWillReceiveProps 方法
*/
koukou(){
this.props.testComponentWillReceiveProps() ;
}
/**
* 在挂载之后调用
*/
componentDidMount(){
console.log("~~ componentDidMout ~~");
alert("~~ componentDidMout ~~") ;
}
/**
* 组件挂载之后 当调用 setState() 的时候 如果此方法返回 true ,则会重新渲染,否则不会
*/
shouldComponentUpdate(nextProps, nextState){
console.log("~~ shouldComponentUpdate ~~");
console.log("shouldComponentUpdate nextState",nextState);
alert("~~ shouldComponentUpdate ~~"+nextState) ;
return true ;
}
/**
* props 改变的时候调用
*/
componentWillReceiveProps(nextProps){
console.log("~~ componentWillReceiveProps ~~");
alert("~~ componentWillReceiveProps ~~") ;
}
/**
* shouldComponentUpdate 返回 true 的时候 将要更新
*/
componentWillUpdate(nextProps, nextState){
console.log("componentWillUpdate nextState",nextState);
console.log(this.state.name);
console.log("~~ componentWillUpdate ~~");
alert("~~ componentWillUpdate ~~") ;
}
/**
* 组件已经更新
*/
componentDidUpdate(){
console.log("~~ componentDidUpdate ~~");
alert("~~ componentDidUpdate ~~") ;
}
/**
* 组件将要卸载
*/
componentWillUnmount(){
console.log("~~ componentWillUnmount ~~");
alert("~~ componentWillUnmount ~~") ;
}
/**
* 组件卸载的方法
*/
_unmout(){
this.props.umout();
}
_forceWithUpdate(){
this.forceUpdate();
}
/**
* 修改属性
*/
_changeProps(){
this.setState({
name:'TigerChain1'
})
}
/**
* 修改 state 方法
*/
_setState(){
var that = this ;
if((that.state.name === "TigerChain1") || (that.state.name="TigerChain")){
that.setState({
name:'TigerChainJun'
});
}
}
}
我们在这里把组件生命周期的 demo 就写完了,具体可以看注释。
5、添加 react react-dom babel 等插件依赖
yarn add react react-dom babel-core babel-loader babel-preset-es2015 babel-preset-react babel-preset-stage-0 webpack webpack-dev-server --dev
这里也不多说,如果不懂的话,可以查看 webpack 这一节。
6、在项目根目录新建 .babelrc 文件并输入以下内容
{
"presets": ["react", "es2015","stage-0"]
}
7、在根目录新建 webpack.config.js 并配置
# webpack.config.js
module.exports = {
entry: __dirname+"/app/main.js",
output:{
path:__dirname + "/public",
filename:"bundle.js"
},
module: {
loaders: [
//babel配置
{
test:/\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
},
devServer:{
contentBase: "./public",//本地服务器所加载的页面所在的目录
historyApiFallback: true,//不跳转
inline: true//实时刷新
}
}
8、配置脚本 package.json
{
"name": "11-lifecycle",
"version": "1.0.0",
"main": "index.js",
"author": "TigerChain",
"license": "ISC",
"scripts":{
"start":"webpack-dev-server --progress --port 8888"
},
"devDependencies": {
"babel-core": "^6.24.0",
"babel-loader": "^6.4.1",
"babel-preset-es2015": "^6.24.0",
"babel-preset-react": "^6.23.0",
"babel-preset-stage-0": "^6.22.0",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"webpack": "^2.3.2",
"webpack-dev-server": "^2.4.2"
}
}
9、运行查看 yarn start 并在浏览器中输入 localhost:8888 如果不出什么问题,那么我们就可以看到如下界面
图中就完整的展示了 React 组件的生命周期。我们回过头再去看前面的生命周期图,就能很好的理解了。请大家务必照着 demo 敲一遍代码,以便加深理解。(老鸟直接略过)
到此为止,我们的 React 组件的生命周期就讲完了。
如果喜欢,就点个喜欢吧。
Demo 地址
https://github.com/tigerchain/react-lesson/tree/master/lesson02/11-lifecycle