生命周期方法


组件的生命周期分成三个状态:

  • 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):组件判断是否重新渲染时调用

挂载:componentWillMount

服务器端和客户端都只调用一次,在初始化渲染执行之前立刻调用。如果在这个方法内调用 setStaterender() 将会感知到更新后的 state,将会执行仅一次,尽管 state 改变了

React.createClass({
  componentWillMount() {
    ...
  }
});

挂载: componentDidMount

在初始化渲染执行之后立刻调用一次,仅客户端有效(服务器端不会调用)。在生命周期中的这个时间点,组件拥有一个 DOM 展现,你可以通过 this.getDOMNode() 来获取相应 DOM 节点。如果想和其它 JavaScript 框架集成,使用 setTimeout 或者 setInterval 来设置定时器,或者发送 AJAX 请求,可以在该方法中执行这些操作。

React.createClass({
  componentDidMount() {
    ...
  }
});

移除: componentWillUnmount

在组件从 DOM 中移除的时候立刻被调用。在该方法中执行任何必要的清理,比如无效的定时器,或者清除在 componentDidMount 中创建的 DOM 元素。

React.createClass({
  componentWillUnmount() {
    ...
  }
});

更新: componentWillReceiveProps

参数:object nextProps

在组件接收到新的 props 的时候调用。在初始化渲染的时候,该方法不会调用。用此函数可以作为 react 在 prop 传入之后, render() 渲染之前更新 state 的机会。老的 props 可以通过 this.props 获取到。在该函数中调用 this.setState() 将不会引起第二次渲染。

React.createClass({
  componentWillReceiveProps(nextProps) {
   this.setState({  })
  }
});

注意:对于 state,没有相似的方法,如果需要在 state 改变的时候执行一些操作,请使用 componentWillUpdate

更新: shouldComponentUpdate

返回:boolean;

参数1:object nextProps

参数2:object nextState

在接收到新的 props 或者 state,将要渲染之前调用。该方法在初始化渲染的时候不会调用,在使用 forceUpdate 方法的时候也不会。如果确定新的 props 和 state 不会导致组件更新,则此处应该 返回 false。默认情况下,shouldComponentUpdate 总会返回 true

React.createClass({
  shouldComponentUpdate(nextProps, nextState) {
  return false
  }
});

如果 shouldComponentUpdate返回false,则 render() 将不会执行,直到下一次 state 改变。(另外,componentWillUpdate 和 componentDidUpdate 也不会被调用。)

更新: componentWillUpdate

参数1:object nextProps

参数2:object nextState

在接收到新的 props 或者 state 之前立刻调用。在初始化渲染的时候该方法不会被调用。

React.createClass({
  componentWillUpdate(nextProps, nextState) {
  ...
  }
});

注意:你不能在刚方法中使用 this.setState()。如果需要更新 state 来响应某个 prop 的改变,请使用 componentWillReceiveProps

更新: componentDidUpdate

参数1:object prevProps

参数2:object prevState

在组件的更新已经同步到 DOM 中之后立刻被调用。该方法不会在初始化渲染的时候调用。使用该方法可以在组件更新之后操作 DOM 元素。

React.createClass({
  componentDidUpdate(nextProps, nextState) {
  ...
  }
});

注意:为了兼容 v0.9,DOM 节点会作为最后一个参数传入。如果使用这个方法,你仍然可以使用 this.getDOMNode()来访问 DOM 节点。

例子: 路由切换时,组件生命周期的变化情况

路由配置如下:

<Route path="/" component={App}>
  <IndexRoute component={Home}/>
  <Route path="invoices/:invoiceId" component={Invoice}/>
  <Route path="accounts/:accountId" component={Account}/>
</Route>

1. 当用户打开应用的 '/' 页面

2. 当用户从 '/' 跳转到 '/invoice/123'

  • App 从 router 中接收到新的 props(例如 childrenparamslocation 等数据), 所以 App 触发了 componentWillReceiveProps 和 componentDidUpdate 两个生命周期方法
  • Home 不再被渲染,所以它将被移除,触发 componentWillUnmount
  • Invoice 首次被挂载 触发 componentWillMount 和 componentDidMount

3. 当用户从 /invoice/123 跳转到 /invoice/789

  • 所有的组件之前都已经被挂载, 所以只是从 router 更新了 props.

4. 当从 /invoice/789 跳转到 /accounts/123

组件的详细说明


getInitialState

在组件挂载之前调用一次。返回值将会作为 this.state 的初始值。

React.createClass({
  getInitialState: function() {
    return {liked: false};
  },
  render: function() {  ...
  }
});

getDefaultProps

在组件类创建的时候调用一次,然后返回值被缓存下来。如果父组件没有指定 props 中的某个键,则此处返回的对象中的相应属性将会合并到 this.props (使用 in 检测属性)。

该方法在任何实例创建之前调用,因此不能依赖于 this.props。另外,getDefaultProps() 返回的任何复杂对象将会在实例间共享,而不是每个实例拥有一份拷贝。

React.createClass({
  getDefaultProps: function() {
    return {liked: false};
  },
  render: function() {  ...
  }
});

propTypes

组件的属性可以接受任意值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。

组件类的PropTypes属性,就是用来验证组件实例的属性是否符合要求

React.createClass({
  propTypes: {
    optionalArray: React.PropTypes.array,
    optionalBool: React.PropTypes.bool,
    optionalFunc: React.PropTypes.func,
    optionalNumber: React.PropTypes.number,
    optionalObject: React.PropTypes.object,
    optionalString: React.PropTypes.string,

    // 所有可以被渲染的对象:数字,字符串,DOM 元素或包含这些类型的数组。
    optionalNode: React.PropTypes.node,

    // React 元素
    optionalElement: React.PropTypes.element,

    // 用 JS 的 instanceof 操作符声明 prop 为类的实例。
    optionalMessage: React.PropTypes.instanceOf(Message),

    // 用 enum 来限制 prop 只接受指定的值。
    optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),

    // 指定的多个对象类型中的一个
    optionalUnion: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.number,
      React.PropTypes.instanceOf(Message)
    ]),

    // 指定类型组成的数组
    optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),

    // 指定类型的属性构成的对象
    optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),

    // 特定形状参数的对象
    optionalObjectWithShape: React.PropTypes.shape({
      color: React.PropTypes.string,
      fontSize: React.PropTypes.number
    }),

    // 以后任意类型加上 `isRequired` 来使 prop 不可空。
    requiredFunc: React.PropTypes.func.isRequired,

    // 不可空的任意类型
    requiredAny: React.PropTypes.any.isRequired,

    // 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。
    customProp: function(props, propName, componentName) {
      if (!/matchme/.test(props[propName])) {
        return new Error('Validation failed!');
      }
    }
  }
});

单个子级

React.PropTypes.element 可以限定只能有一个子级传入。
var MyComponent = React.createClass({
  propTypes: {
    children: React.PropTypes.element.isRequired
  },
  render: function() {
    return (
      <div>
        {this.props.children} // 有且仅有一个元素,否则会抛异常。
      </div>
    );
  }
});

默认 Prop 值

var ComponentWithDefaultProps = React.createClass({
  getDefaultProps: function() {
    return {
      value: 'default value'
    };
  }
});

当父级没有传入 props 时,getDefaultProps() 可以保证 this.props.value 有默认值,注意 getDefaultProps 的结果会被 缓存。得益于此,你可以直接使用 props,而不必写手动编写一些重复或无意义的代码


ref

组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref 属性

<input type="text" ref="myTextInput" />
this.refs.myTextInput.focus();

this.props.children

this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点

mixins

组件是 React 里复用代码最佳方式,但是有时一些复杂的组件间也需要共用一些功能。React 使用 mixins 来解决这类问题。

一个通用的场景是:一个组件需要定期更新。用 setInterval() 做很容易,但当不需要它的时候取消定时器来节省内存是非常重要的。React 提供 生命周期方法 来告知组件创建或销毁的时间。下面来做一个简单的 mixin,使用 setInterval() 并保证在组件销毁时清理定时器。

var SetIntervalMixin = {
  componentWillMount: function() {
    this.intervals = [];
  },
  setInterval: function() {
    this.intervals.push(setInterval.apply(null, arguments));
  },
  componentWillUnmount: function() {
    this.intervals.map(clearInterval);
  }
};

var TickTock = React.createClass({
  mixins: [SetIntervalMixin], // 引用 mixin
  getInitialState: function() {
    return {seconds: 0};
  },
  componentDidMount: function() {
    this.setInterval(this.tick, 1000); // 调用 mixin 的方法
  },
  tick: function() {
    this.setState({seconds: this.state.seconds + 1});
  },
  render: function() {
    return (
      <p>
        React has been running for {this.state.seconds} seconds.
      </p>
    );
  }
});

React.render(
  <TickTock />,
  document.getElementById('example')
);

关于 mixin 值得一提的优点是,如果一个组件使用了多个 mixin,并用有多个 mixin 定义了同样的生命周期方法(如:多个 mixin 都需要在组件销毁时做资源清理操作),所有这些生命周期方法都保证会被执行到。方法执行顺序是:首先按 mixin 引入顺序执行 mixin 里方法,最后执行组件内定义的方法。

statics

statics 对象允许你定义静态的方法,这些静态的方法可以在组件类上调用

var MyComponent = React.createClass({

statics: {

  customMethod: function(foo) {

    return foo === 'bar';

}

},

render: function() {

}

});

MyComponent.customMethod('bar'); // true

顶层 API


  • React.createClass

创建一个组件类,并作出定义。组件实现了 render() 方法,该方法返回一个子级。该子级可能包含很深的子级结构。组件与标准原型类的不同之处在于,你不需要使用 new 来实例化。 组件是一种很方便的封装,可以(通过 new )为你创建后台实例。

  • React.createElement

创建并返回一个新的指定类型的 ReactElement。type 参数可以是一个 html 标签名字字符串(例如,“div”,“span”,等等),或者是 ReactClass (通过 React.createClass 创建的)。

  • React.createFactory

返回一个生成指定类型 ReactElements 的函数。比如 React.createElement,type 参数可以是一个 html 标签名字字符串(例如,“div”,“span”,等等),或者是 ReactClass

  • React.render

渲染一个 ReactElement 到 DOM 中,放在 container 指定的 DOM 元素下,返回一个到该组件的引用。

如果 ReactElement 之前就被渲染到了 container 中,该函数将会更新此 ReactElement,仅改变需要改变的 DOM 节点以展示最新的 React 组件。

如果提供了可选的回调函数,则该函数将会在组件渲染或者更新之后调用。

  • React.unmountComponentAtNode

从 DOM 中移除已经挂载的 React 组件,清除相应的事件处理器和 state。如果在 container 内没有组件挂载,这个函数将什么都不做。如果组件成功移除,则返回 true;如果没有组件被移除,则返回 false

  • React.renderToString

把组件渲染成原始的 HTML 字符串。该方法应该仅在服务器端使用。React 将会返回一个 HTML 字符串。你可以在服务器端用此方法生成 HTML,然后将这些标记发送给客户端,这样可以获得更快的页面加载速度,并且有利于搜索引擎抓取页面,方便做 SEO。

如果在一个节点上面调用 React.render(),并且该节点已经有了服务器渲染的标记,React 将会维护该节点,并且仅绑定事件处理器,保证有一个高效的首屏加载体验。

  • React.renderToStaticMarkup

string renderToStaticMarkup(ReactElement element)

和 renderToString 类似,除了不创建额外的 DOM 属性,例如 data-react-id,因为这些属性仅在 React 内部使用。如果你想用 React 做一个简单的静态页面生成器,这是很有用的,因为丢掉额外的属性能够节省很多字节。

  • React.isValidElement

boolean isValidElement(* object)

判断对象是否是一个 ReactElement。

  • React.DOM

React.DOM 运用 React.createElement 为 DOM 组件提供了方便的包装。该方式仅在未使用 JSX 的时候适用。例如,React.DOM.div(null, 'Hello World!')

  • React.PropTypes

React.PropTypes 包含了能与组件 propTypes 对象共用的类型,用于验证传入组件的 props。更多有关 propTypes 的信息,参考复用组件

  • React.initializeTouchEvents

initializeTouchEvents(boolean shouldUseTouch)

配置 React 的事件系统,使 React 能处理移动设备的触摸( touch )事件。

  • React.Children

React.Children 为处理 this.props.children 这个封闭的数据结构提供了有用的工具。

React.Children.map

object React.Children.map(object children, function fn [, object context])

在每一个直接子级(包含在 children 参数中的)上调用 fn 函数,此函数中的 this 指向 上下文。如果 children是一个内嵌的对象或者数组,它将被遍历:不会传入容器对象到 fn 中。如果 children 参数是 null 或者 undefined,那么返回 null 或者 undefined 而不是一个空对象。

React.Children.forEach

React.Children.forEach(object children, function fn [, object context])

类似于 React.Children.map(),但是不返回对象。

React.Children.count

number React.Children.count(object children)

返回 children 当中的组件总数,和传递给 map 或者 forEach 的回调函数的调用次数一致。

React.Children.only

object React.Children.only(object children)

返回 children 中仅有的子级。否则抛出异常。

组件 API


  • setState

合并 nextState 和当前 state。这是在事件处理函数中和请求回调函数中触发 UI 更新的主要方法。另外,也支持可选的回调函数,该函数在 setState 执行完毕并且组件重新渲染完成之后调用

注意:

    1. 绝对不要直接改变 this.state
    2. setState() 不会立刻改变 this.state,而是创建一个即将处理的 state 转变。在调用该方法之后获取 this.state 的值可能会得到现有的值,而不是最新设置的值。
    3. 不保证 setState() 调用的同步性,为了提升性能,可能会批量执行 state 转变和 DOM 渲染。
    4. setState() 将总是触发一次重绘,除非在 shouldComponentUpdate() 中实现了条件渲染逻辑。如果使用可变的对象,但是又不能在 shouldComponentUpdate() 中实现这种逻辑,仅在新 state 和之前的 state 存在差异的时候调用 setState() 可以避免不必要的重新渲染。
  • replaceState

类似于 setState(),但是删除之前所有已存在的 state 键,这些键都不在 nextState 中。

  • forceUpdate()

render() 方法从 this.props 或者 this.state 之外的地方读取数据,你需要通过调用 forceUpdate() 告诉 React 什么时候需要再次运行 render()。如果直接改变了 this.state,也需要调用 forceUpdate()

调用 forceUpdate() 将会导致 render() 方法在相应的组件上被调用,并且子级组件也会调用自己的 render(),但是如果标记改变了,那么 React 仅会更新 DOM

  • getDOMNode

如果组件已经挂载到了 DOM 上,该方法返回相应的本地浏览器 DOM 元素。从 DOM 中读取值的时候,该方法很有用,比如获取表单字段的值和做一些 DOM 操作。当 render 返回 null 或者 false 的时候,this.getDOMNode() 返回 null

  • isMounted

如果组件渲染到了 DOM 中,isMounted() 返回 true。可以使用该方法保证 setState() 和 forceUpdate() 在异步场景下的调用不会出错

  • setProps

调用 setProps() 来改变组件的属性,触发一次重新渲染。另外,可以传递一个可选的回调函数,该函数将会在 setProps 完成并且组件重新渲染完成之后调用

注意:

刚方法仅在根组件上面调用。也就是说,仅在直接传给 React.render() 的组件上可用,在它的子级组件上不可用。如果你倾向于在子组件上使用 setProps(),不要利用响应式更新,而是当子组件在 render() 中创建的时候传入新的 prop 到子组件中。

  • replaceProps

类似于 setProps(),但是删除所有已存在的 props,而不是合并新旧两个 props 对象

react- 相关的更多相关文章

  1. 【原】整理的react相关的一些学习地址,包括 react-router、redux、webpack、flux

    因为平时经常去网上找react相关的一些地址,找来找去很麻烦,所以自己整理了一下,不过前面部分不是我整理的, 是出自于:http://www.cnblogs.com/aaronjs/p/4333925 ...

  2. React相关知识和经验的碎片化记录

    React相关知识和经验的碎片化记录 1.Warning: validateDOMNesting(...): Whitespace text nodes cannot appear as a chil ...

  3. 常用的package.json以及React相关

    常用的package.json以及React相关 前言 package.json 的简单介绍 简单版的 package.json 必备属性(name & version) name 字段 ve ...

  4. react相关知识点

    1.react内联样式写法: <div style={{width:'200px',height:'100px',border:'1px solid red'}}> </div> ...

  5. react相关

    react 简单入门 ant 蚂蚁金服react组件 redux 阮一峰入门react material-ui组件库 webpack入门 http://www.jianshu.com/p/42e115 ...

  6. REACT相关资料合集

    ===实例=== https://github.com/jesseskinner/react-webpack-demo ===UI组件库=== https://github.com/amazeui/a ...

  7. React相关:npm,ES6,

    1.NPM: 参考:npm使用入门  npm 学习笔记整理 2.ES6参考:ES6 let命令:ES6新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块 ...

  8. 记录一次react相关总结

    背景说明:元旦接到一个管理后台的项目,是一个关于自定义专题的项目.通过后台的配置自定义专题,前端根据专题模块进行渲染数据.由于管理后台是react做的前后分离,对于一个后端的我来说写写js也算是浅尝一 ...

  9. react相关知识点链接整理

    1.React组件之间的通信 2.中间件做代理解决跨域问题 3.不要再问我跨域的问题了 4.React 组件数据流 && 组件间沟通 5.如何理解虚拟DOM 6.react性能调谐与d ...

  10. react相关小技巧

    一.我们在项目中切换路由的时候可能会遇到 Warning: setState(...): Can only update a mounted or mounting component. This u ...

随机推荐

  1. uoj#450. 【集训队作业2018】复读机(单位根反演)

    题面 传送门 题解 我的生成函数和单位根反演的芝士都一塌糊涂啊-- \(d=1\),答案就是\(k^n\)(因为这里\(k\)个复读机互不相同,就是说有标号) \(d=2\),我们考虑复读机的生成函数 ...

  2. POI生成Excel强制换行

    自动换行的设置: HSSFCellStyle cellStyle=workbook.createCellStyle(); cellStyle.setWrapText(true); cell.setCe ...

  3. 2019-5-1 maven学习笔记

    一.maven的好处 同样的项目使用maven工程来实现,由于不需要导入很多jar包,源码很小 原理:根据坐标到项目的仓库里查找需要的依赖 二.安装步骤 1.到http://maven.apache. ...

  4. Functions that return a function

    javascript学习中,经常会遇到闭包的问题,然后闭包的很多例子中又会遇到很多返回函数的闭包的例子程序.因为对闭包的理解还不够透彻,然后对于Functions rerurn a function产 ...

  5. P2925 [USACO08DEC]干草出售Hay For Sale

    传送门 把每体积的干草价值看成一,就变成求最大价值 直接上背包就行了 注意优化常数 #include<iostream> #include<cstdio> #include&l ...

  6. 权限知识中的AIX ACL

    Aix ACL是对标准权限位的扩展.通过修改分配给个人或组的标准权限,对每个文件或目录进行更精细的控制. 对每个组或用户,有3种权限分配情况: PERMIT : 准许对文件或目录的特定权限. DEMY ...

  7. A. The number of positions

    A. The number of positions time limit per test 0.5 second memory limit per test 256 megabytes input ...

  8. vue父子组件通信(prop)

    先定义子组件,注册prop接收父组件传递的值 <template> <div> <div>{{message}}(子组件)</div> </div ...

  9. 用NaviCat创建存储过程批量添加测试数据

    打开navicat连接上数据库,然后打开左上角函数,新建一个函数. BEGIN DECLARE i int; --声明变量 DECLARE groupid int; set i=LAST_INSERT ...

  10. JavaSE---线程同步

    1.当多个线程同时访问同一个数据时,容易出现线程安全问题,必须进行线程同步: 2.解决方案: 1.1 Java的多线程引入了  同步监视器  ,使用同步监视器的通用方法就是  同步代码块 //线程开始 ...