React - component组件的生命周期

component的生命周期图
getDefaultProps
object getDefaultProps()
执行过一次后,被创建的类会有缓存,映射的值会存在this.props
,前提是这个prop不是父组件指定的
这个方法在对象被创建之前执行,因此不能在方法内调用this.props
,另外,注意任何getDefaultProps()
返回的对象在实例中共享,不是复制
getInitialState
object getInitialState()
控件加载之前执行,返回值会被用于state的初始化值
componentWillMount
void componentWillMount()
执行一次,在初始化render
之前执行,如果在这个方法内调用setState
,render()
知道state发生变化,并且只执行一次
render
ReactElement render()
render的时候会调用render()
会被调用
调用render()
方法时,首先检查this.props
和this.state
返回一个子元素,子元素可以是DOM组件或者其他自定义复合控件的虚拟实现
如果不想渲染可以返回null或者false,这种场景下,React渲染一个<noscript>
标签,当返回null或者false时,ReactDOM.findDOMNode(this)
返回null render()
方法是很纯净的,这就意味着不要在这个方法里初始化组件的state,每次执行时返回相同的值,不会读写DOM或者与服务器交互,如果必须如服务器交互,在componentDidMount()
方法中实现或者其他生命周期的方法中实现,保持render()
方法纯净使得服务器更准确,组件更简单
componentDidMount
void componentDidMount()
在初始化render之后只执行一次,在这个方法内,可以访问任何组件,componentDidMount()
方法中的子组件在父组件之前执行
从这个函数开始,就可以和 JS 其他框架交互了,例如设置计时 setTimeout 或者 setInterval,或者发起网络请求
shouldComponentUpdate
- 1
- 2
- 3
- 1
- 2
- 3
这个方法在初始化render
时不会执行,当props或者state发生变化时执行,并且是在render
之前,当新的props
或者state
不需要更新组件时,返回false
- 1
- 2
- 3
- 1
- 2
- 3
当shouldComponentUpdate
方法返回false时,讲不会执行render()
方法,componentWillUpdate
和componentDidUpdate
方法也不会被调用
默认情况下,shouldComponentUpdate
方法返回true防止state
快速变化时的问题,但是如果·state
不变,props
只读,可以直接覆盖shouldComponentUpdate
用于比较props
和state
的变化,决定UI是否更新,当组件比较多时,使用这个方法能有效提高应用性能
componentWillUpdate
- 1
- 2
- 3
- 1
- 2
- 3
当props
和state
发生变化时执行,并且在render
方法之前执行,当然初始化render时不执行该方法,需要特别注意的是,在这个函数里面,你就不能使用this.setState
来修改状态。这个函数调用之后,就会把nextProps
和nextState
分别设置到this.props
和this.state
中。紧接着这个函数,就会调用render()
来更新界面了
componentDidUpdate
- 1
- 2
- 3
- 1
- 2
- 3
组件更新结束之后执行,在初始化render
时不执行
componentWillReceiveProps
- 1
- 2
- 3
- 1
- 2
- 3
当props
发生变化时执行,初始化render
时不执行,在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()
来更新你的组件状态,旧的属性还是可以通过this.props
来获取,这里调用更新状态是安全的,并不会触发额外的render
调用
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
componentWillUnmount
void componentWillUnmount()
当组件要被从界面上移除的时候,就会调用componentWillUnmount()
,在这个函数中,可以做一些组件相关的清理工作,例如取消计时器、网络请求等
总结
React Native的生命周期就介绍完了,其中最上面的虚线框和右下角的虚线框的方法一定会执行,左下角的方法根据props
state
是否变化去执行,其中建议只有在componentWillMount
,componentDidMount
,componentWillReceiveProps
方法中可以修改state
值
英文地址:https://facebook.github.io/react/docs/component-specs.html#lifecycle-methods
组件的生命周期
组件的生命周期分成三个状态:
Mounting:已插入真实 DOM
Updating:正在被重新渲染
Unmounting:已移出真实 DOM
React 为每个状态都提供了两种处理函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用,三种状态共计五种处理函数。
componentWillMount()
componentDidMount()
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount()
此外,React 还提供两种特殊状态的处理函数。
componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用
React - ES6 - Ajax获取接口数据渲染到UI组件【完整示例】

本站PHP后端接口: http://code.liuxinxiu.com/php/Interface/Jsoncallback.php?GUID=1&&Jsoncallback=1
本实例用 ES5 + JSX 语法编写[对应实例] : http://liuxinxiu.com/React_Ajax_setState_Render_UI_ES5/
- /****** ES6输入文件[调用模块依赖] ******/
- import React, { Component, PropTypes } from 'react'
- import $ from 'n-zepto'
- /****** ES5输入文件[调用模块依赖] ******/
- //var React=require('react');
- //var $=require('n-zepto');
- //import * as from './commentList.js'
- //import list from './commentList.js';
- /****** 本地模拟Array数据******/
- var movies = [
- {
- id: 1,
- name: '速度与激情001',
- date: 2011
- },
- {
- id: 2,
- name: '速度与激情002',
- date: 2009
- }
- ];
- /****** 外部子组件map数组当做模板之用 ES5 + JSX 语法编写 ******/
- var MoviesList = React.createClass({
- render: function () {
- // this.props 用于从组件外部传入数据
- var _movies = this.props._movies;
- return (
- <li className="datali">
- {_movies.id}-{_movies.name}
- </li>
- )
- }
- });
- /****** 外部子组件map数组当做模板之用 ES6 + JSX 语法编写 ******/
- let CommentList=class CommentList extends Component {
- constructor(props) {
- super(props); //ES6调用父类构造函数super不能少!
- this.state = {
- wording: '你好呀, '
- };
- }
- /****** Ajax子组件中[主体模板] ******/
- render(){
- return <ul>{this.props.comments.map(this.renderComment)}</ul>;
- }
- /****** Ajax子组件中[嵌套模板] ******/
- renderComment({plat,type,name,guid,cre_time,lottery}){
- return (
- <li>{plat}--{type}--{name}--{guid}--{cre_time}--{lottery}</li>
- )
- }
- }
- /****** 使用ES6 + JSX 语法编写 class xx extends React.Component{} 创建一个组件 ******/
- class CommentListContainer extends Component {
- /****** [ES6-constructor||ES5-getInitialState] ******/
- constructor(){
- super();
- this.state = {
- loading: true,
- title: '我喜欢的电影',
- movies: [],
- comments: []
- }
- }
- componentDidMount(){
- $.ajax({
- type: 'GET',
- url: 'http://code.liuxinxiu.com/php/Interface/Jsoncallback.php',
- data: {GUID:'1'},
- dataType:'jsonp', //告诉Ajax调用$jsonp
- jsonp: "Jsoncallback", //zpeto-1.2支持自定义回调名
- success: function(data){
- var yy=JSON.stringify(data);
- var tlist=JSON.stringify(data.enttityList);
- //console.log(tlist);
- //console.log(this.state.title+'22');
- this.setState({
- comments:data.enttityList,
- lottery:data.enttityList[0].lottery
- });
- var commentsStr=JSON.stringify(this.state.comments);
- console.log("\n--->>commentsStr:\n"+commentsStr); //查看获取的数据
- //console.log(this.state.comments+'33')
- }.bind(this),
- error: function(xhr, type){
- alert(xhr+type+'Ajax error!');
- }
- });
- //console.log(this.state.comments+'++++--!!'); //ajax底下拿不到结果因为提前于异步
- }
- render(){
- return <CommentList comments={this.state.comments}/>;
- }
- }
- /****** ES5输出给router ******/
- //module.exports=DemoComponent;
- /****** ES6输出给router ******/
- export default CommentListContainer;
React - ES5 - Ajax获取接口数据渲染到UI组件【完整示例】

本站PHP后端接口: http://code.liuxinxiu.com/php/Interface/Jsoncallback.php?GUID=1&&Jsoncallback=1
本实例用 ES6 + JSX 语法编写[对应实例] : http://liuxinxiu.com/React_Ajax_setState_Render_UI_ES6/
- //import React, { Component, PropTypes } from 'react'
- //import $ from 'n-zepto'
- var React=require('react'); //Es-5
- var $=require('n-zepto'); //Es-5
- //import * as from './commentList.js'
- //import list from './commentList.js';
- /****** 外部子组件map数组当做模板之用 ******/
- var MoviesList = React.createClass({
- render: function () {
- // this.props 用于从组件外部传入数据
- ar _movies = this.props._movies;
- return (
- <li className="datali">
- {_movies.id}-{_movies.name}
- </li>
- )
- }
- });
- /****** 本地模拟Array数据******/
- var movies = [
- {
- id: 1,
- name: '速度与激情001',
- date: 2011
- },
- {
- id: 2,
- name: '速度与激情002',
- date: 2009
- }
- ];
- /****** 使用Es5语法 React.createClass 创建一个组件 ******/
- var DemoComponent = React.createClass({
- /****** 使用 getInitialState 的返回值作为数据的默认值 ******/
- getInitialState: function () {
- // this.state 用于存储数据comments被Ajax赋值要先定义个名称
- return {
- loading: true,
- title: '我喜欢的电影',
- movies: [],
- comments: []
- }
- },
- componentDidMount: function() {
- $.ajax({
- type: 'GET',
- url: 'http://code.liuxinxiu.com/php/Interface/Jsoncallback.php',
- data: {GUID:'1'},
- dataType:'jsonp', //告诉Ajax调用$jsonp
- jsonp: "Jsoncallback", //zpeto-1.2支持自定义回调名
- success: function(data){
- var yy=JSON.stringify(data);
- var tlist=JSON.stringify(data.enttityList);
- console.log(tlist);
- //console.log(this.state.title+'22')
- this.setState({
- comments:data.enttityList,
- lottery:data.enttityList[0].lottery
- });
- var slist=JSON.stringify(this.state.comments);
- console.log(slist)
- //console.log(this.state.comments+'33')
- }.bind(this),
- error: function(xhr, type){
- alert(xhr+type+'Ajax error!'); //error
- }
- });
- //console.log(this.state.comments+'++++--!!'); //ajax底下拿不到结果因为提前于异步
- },
- render: function () {
- // this.state 用于存储当前的数据
- var comments = this.state.comments;
- //var dataHtml=movies.map(<p>{name}</p>);// 注意这里 bind(this) 修正了上下文
- /****** Movies子模板 ******/
- function renderMovies({id,name}){
- return <li>{id}-{name}</li>;
- }
- /****** Movies大模板[内嵌子模板] ******/
- //var dataHtml = movies.map(renderMovies);
- /****** Movies大模板[外调子模板] ******/
- var dataHtml = movies.map(function(movies){
- return (
- <MoviesList _movies={movies}/>
- )
- }.bind(this));// 注意这里 bind(this) 修正了上下文
- //console.log('movies:'+movies+'--'+'dataHtml:'+dataHtml);
- /****** Ajax子模板******/
- function renderComment({plat,type,name,guid,cre_time,lottery}){
- return <li>{plat}--{type}--{name}--{guid}--{cre_time}--{lottery}</li>;
- }
- /****** Ajax大模板 ******/
- var AjaxHtml = this.state.comments.map(renderComment);
- //var AjaxHtml='11'
- console.log('comments:'+comments+'--'+'AjaxHtml:'+AjaxHtml);
- return (
- <ul>{AjaxHtml}</ul>
- )
- }
- });
- /****** ES5输出给router ******/
- module.exports=DemoComponent;
- /****** ES6输出给router ******/
- //export default DemoComponent;
使用ES5||ES6 -- 输入文件示例 [调用所依赖的模块]:
- /****** ES5调用依赖模块[require]被打包会自动生成关联代码 ******/
- var MyComponent = require('./components/movie-list');
- /****** ES6调用依赖模块 ******/
- import MyComponent from './components/movie-list';
使用ES5||ES6 -- 输出文件示例[输出给被依赖模块]:
- /****** ES5输出给router ******/
- module.exports=DemoComponent;
- /****** ES6输出给router ******/
- //export default DemoComponent;
使用ES5 -- 创建一个组件:
- /****** 使用Es5语法 React.createClass 创建一个组件 ******/
- var DemoComponent = React.createClass({
- /****** 使用 getInitialState 的返回值作为数据的默认值(!return) ******/
- getInitialState: function () {
- return {
- loading: true,
- title: '我喜欢的电影',
- // 注意这里将 外部传入的数据赋值给了 this.state
- movies: []
- }
- },
- /****** 输出HTML模板,此处可以调用子组件******/
- render: function () {
- return (
- <div className="component-hello">
- {this.state.title}
- </div>
- )
- }
- });
使用ES5 -- map遍历当前Array并调用渲染数据的[外部]子组件:
- /****** 使用Es5语法 遍历数组并调用外部子组件 ******/
- var MoviesList=React.createClass({...});
- var dataHtml = movies.map(function(movies){
- return (
- <MoviesList _movies={movies}/>
- )
- }.bind(this));// 注意这里 bind(this) 修正了上下文
- return (
- <ul>{dataHtml}</ul>
- )
- /****** 外部子组件map数组当做模板之用 ******/
- var MoviesList = React.createClass({
- render: function () {
- // this.props 用于从组件外部传入数据
- var _movies = this.props._movies;
- return (
- <li className="datali">
- {_movies.id}-{_movies.name}
- </li>
- )
- }
- });
使用ES5 -- map遍历当前Array并调用渲染数据的[内部]子组件:
- /****** 使用Es5语法 遍历数组并调用内部子组件 ******/
- function renderMovies({id,name}){
- return <li>{id}-{name}</li>;
- }
- var dataHtml = movies.map(renderMovies);
- return (
- <ul>{dataHtml}</ul>
- )
Ajax获取接口数据并设置到state :
- componentDidMount(){
- $.ajax({
- type: 'GET',
- url: 'http://code.liuxinxiu.com/php/Interface/Jsoncallback.php', //JSONP接口
- data: {GUID:'1'},
- dataType:'jsonp', //告诉Ajax调用$jsonp
- jsonp: "Jsoncallback", //zpeto-1.2支持自定义回调名
- success: function(data){
- var yy=JSON.stringify(data);
- var tlist=JSON.stringify(data.enttityList);
- //console.log(tlist);
- //console.log(this.state.title+'22');
- this.setState({
- comments:data.enttityList,
- lottery:data.enttityList[0].lottery
- });
- var commentsStr=JSON.stringify(this.state.comments);
- console.log("\n--->>commentsStr:\n"+commentsStr); //查看获取的数据
- //console.log(this.state.comments+'33')
- }.bind(this),
- error: function(xhr, type){
- alert(xhr+type+'Ajax error!');
- }
- });
- //console.log(this.state.comments+'++++--!!'); //ajax底下拿不到结果因为提前于异步
- }
react 的事件调用分类
- 触摸事件:onTouchCancel\onTouchEnd\onTouchMove\onTouchStart
- (只会在移动设备上接受)
- 键盘事件:onKeyDown\onKeyPress\onKeyUp
- 剪切事件:onCopy\onCut\onPaste
- 表单事件:onChange\onInput\onSubmit
- 焦点事件:onFocus\onBlur
- UI元素:onScroll(移动设备是手指滚动和PC的鼠标滑动)
- 滚动事件:onWheel(鼠标滚轮)
- 鼠标类型:onClick\onContextMenu(右键)\onDoubleClick\onMouseDown\onMouseEnter\
- onMouseLeave\onMouseMove\onMouseOut\onMouseOver\onMouseUp
- onDrag\onDrop\onDragEnd\onDragEnter\onDragExit\onDragLeave\onDragOver\onDragStart
react 嵌套路由相关

/src/js/app.js
- import React, { PropTypes, Component } from 'react';
- import {render} from 'react-dom'; //render((_component),Dom);
- //import ReactDOM from 'react-dom'; //ReactDOM.render((_component),Dom);
- import getRouter from './getRouter';
- import { Router, Route, Link, IndexRoute, hashHistory } from 'react-router';
- /* using an ES6 transpiler, like babel */
- //import { createHistory } from 'history/createBrowserHistory'
- //import createBrowserHistory from 'history/createBrowserHistory';
- /* Import Component */
- import Hello from '../components/hello/hello.jsx'
- import Other from '../components/other/other.jsx'
- /* ensure test */
- require.ensure(['./test'],function(require){
- var aModule = require('./test');
- console.log("xxxx");
- },'test');
- /* create history for router */
- //const history = createHistory()
- /* Router Config */
- render((
- <Router history={hashHistory}>
- <Route path="/" component={getRouter}>
- <IndexRoute component={Hello} />
- <Route path="other" component={Other} />
- </Route>
- </Router>
- ), document.getElementById('app'));
/src/js/getRouter.js
- import React, { PropTypes, Component } from 'react';
- export default React.createClass ({
- render() {
- return <div>
- {this.props.children}
- </div>
- }
- });
/src/components/hello/hello.jsx
- import React, { PropTypes, Component } from 'react';
- /* 导入组件样式hello.css */
- import styles from './css/hello.css';
- //require("./css/hello.css");
- class Hello extends React.Component {
- render(){
- return (
- <div className="hello">
- <p>Hello World!!!!!!!...</p>
- <p>cll不错!</p>
- </div>
- );
- };
- };
- export default Hello;
/src/components/other/other.jsx
- class Other extends React.Component {
- render() {
- return (
- <div>
- <p>this is other component!!!</p>
- <p>111111111cll不错!</p>
- </div>
- )
- }
- }
- export default Other;