ReactJS入门(三)—— 顶层API

本文基本跟着官方文档把API都走一遍,但会有实例来解释应该怎么用,木有比我更详细的API文档咯。

 

React.createClass

参数:CONFIG(object)

创建一个ReactClass(组件类),参数是一个对象且必须带有 render 属性方法,该方法必须返回一个封闭的容器(容器内可以有其它不限结构的容器)或 null/false(表示啥都不渲染):

    var Component = React.createClass({
        render: function() {
            return this.props.a==1 ? 

标题

123

: null } }); React.render( , document.body );

注意!在该方法里面,所有的 this 都会在最终调用时自动地晚绑定到当前组件的构造器上(在本文最后有个有趣的小例子说明)。

React.createElement

参数:TYPE(string/ReactClass),[PROPS(object)],[CHILDREN(ReactElement)]

创建一个指定类型的React元素,注意第三个参数CHILDREN可以是任意个React元素:

    var Component = React.createClass({
        render: function() {
            return this.props.a==1 ? 

123

: null } }); React.render( React.createElement('div', null, React.createElement( 'p', null, React.createElement('span', null, 'Hello,'), React.createElement('span', null, 'world,'), React.createElement( Component, {a : 1}) ) ), document.body );

其实 React.createElement 是一个语法糖:

var reactElement = React.createElement(type, props, children);
//等价于下面两行:
var div = React.createFactory('div');
var reactDivElement = div(props, children);

React.cloneElement

参数:TYPE(ReactElement),[PROPS(object)],[CHILDREN(ReactElement)]

克隆并返回一个新的 ReactElement (内部子元素也会跟着克隆),新返回的元素会保留有旧元素的 props、ref、key,也会集成新的 props(只要在第二个参数中有定义)。

        var Hello = React.createClass({
            render: function() {
                var span = VaJoy;
                var newSpan = React.cloneElement(span, {b:'2'}, CNBlog);
                console.log(newSpan.props);
                return 
Hello {span},{newSpan}
; //Hello VaJoy,CNBlog } }); React.render(, document.body);

要注意的是,createElement 的第一个参数必须是字符串或 ReactClass,而在 cloneElement 里第一个参数应该是 ReactElement:

        var Li = React.createClass({
            render: function() {
                return 
  • {this.props.i}
  • } }); var Ul = React.createClass({ deal : function(child, index){ //注意下面这行换成 createElement 会报错!因为child是ReactElement而不是ReactClass或字符串 return React.cloneElement(child, {i:index}); }, render: function() { return
      {this.props.children.map(this.deal)}
    ; } }); React.render((
    ), document.body);

    React.createFactory

    参数:TYPE(string/ReactElement

    返回一个某种类型的ReactElement工厂函数,可以利用返回的函数来创建一个ReactElement(配置 props 和 children):

        var Component = React.createClass({
            render: function() {
                return this.props.a==1 ? 

    123

    : null } }); var p = React.createFactory(Component), ReactElementP = p({a:1}), div = React.createFactory('div'), ReactElementDiv = div(null, ReactElementP); React.render( ReactElementDiv, document.body );

    React.render

    参数:REACTELEMENT(ReactElement),CONTAINER(DOMElement),[CALLBACK(function)]

    渲染一个 ReactElement 到 container 指定的 DOM 中,并返回一个到该组件的引用。如果提供了可选的回调函数,则该函数将会在组件渲染或者更新之后调用:

        var Component = React.createClass({
            render: function() {
                return this.props.a==1 ? 

    123

    : null } }); var p = React.render( , document.body, function(){ console.log('OK') } ); setTimeout(function(){ console.log(p.props.a); //打印出“1” }, 2000)

    因此如果我们希望在组件外部获取到组件内部(能通过 this 访问)的东西,可以将 React.render 的返回值赋予一个变量,在后续调用该变量即可。

    React.unmountComponentAtNode

    参数:CONTAINER(DOMElement)

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

        var Component = React.createClass({
            render: function() {
                return this.props.a==1 ? 

    123

    : null } }); React.render( , document.body ); setTimeout(function(){ var isUnmount = React.unmountComponentAtNode(document.body); console.log(isUnmount); //打印出true }, 2000)

    React.renderToString

    参数:REACTELEMENT(ReactElement)

    React为服务端提供的一个方法,可以直接输出 ReactElement 为 HTML 字符串,将这些标记发送(比如 res.write(HTMLString))给客户端,可以获得更快的页面加载速度,并且有利于搜索引擎抓取页面,方便做 SEO(主要是百度不争气,谷歌早可以从内存中去抓最终生成的HTML内容了):

        var Component = React.createClass({
            render: function() {
                return this.props.a==1 ? 

    123

    : null } }); var com = , comHTML = React.renderToString(com); console.log(comHTML); //输出“

    123

    React.renderToStaticMarkup

    参数:REACTELEMENT(ReactElement)

    类似 React.renderToString ,但只生成纯粹的HTML标记字符串,不会包含类似 data-reactid 之类的React属性,从而节省字节数:

            var Component = React.createClass({
                render: function() {
                    return this.props.a==1 ? 

    123

    : null } }); var com = , comHTML = React.renderToStaticMarkup(com); console.log(comHTML); //输出“

    123

    React.isValidElement

    参数:SOMETHING

    判断参数是否一个合法的 ReactElement,并返回 Boolean 值:

            var Component = React.createClass({
                render: function() {
                    return this.props.a==1 ? 

    123

    : null } }); var com = , com2 = ''; console.log(React.isValidElement(com)); //true console.log(React.isValidElement(com2)); //false

    React.DOM.tag

    参数:ATTRIBUTE(object/nullCHILDREN(string/ReactElement)

    常规是用于在非 JSX 下来创建 ReactElement,tag 表示相应的DOM类型(比如“div”、“p”)。另外首个参数可以定制相关的 DOM 属性(比如“name”),第二个参数表示 DOM 内的内容:

            var div = React.DOM.div({name : 'div1'}, 'HELLO ', React.DOM.span(null, WORLD));
            React.render(
                div, document.body
            )

    生成结果:

    <div name="div1" data-reactid=".0">
      <span data-reactid=".0.0">HELLOspan>
      <span data-reactid=".0.1">
        <em data-reactid=".0.1.0">WORLDem>
      span>
    div>

    React.PropTypes

    用于组件内部验证传入 Props 的类型,如果传入的类型不匹配,React 会打印出警告:

            var Component = React.createClass({
                propTypes : {
                    a : React.PropTypes.number.isRequired, //必须传入一个名为“a”、类型为number的props
                    callback : React.PropTypes.func   //如果传入了名为“callback”的props,其类型必须是函数
                },
                render : function() {
                    return this.props.a==1 ? <p onClick={this.props.callback}>123p> : null
                }
            });
    
            var cb = function(){
                alert('click!')
            };
    
            React.render(
                <Component a="1" callback={cb} />, document.body
            )

    上方代码中,我们虽然给组件传入了名为“a”的 props,但其类型为字符串,不是我们期望的 number 类型,故 React 会报警告:

    更多的 Props 期望类型可见官方例子:

    React.createClass({
      propTypes: {
        // 可以声明 prop 为指定的 JS 基本类型。默认
        // 情况下,这些 prop 都是可传可不传的。
        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),
    
        // 指定Object对象内各属性的类型
        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!');
          }
        }
      },
      /* ... */
    });
    View Code

    React.initializeTouchEvents

    参数:SholdUserTouch(boolean

    开启或关闭 React 的触摸事件机制,传入参数 true 使 React 能处理移动设备的触摸( touch )事件:

            React.initializeTouchEvents(true);
            var Component = React.createClass({
                render : function() {
                    return 

    this.props.callback}>123

    } }); var cb = function(){ alert('touch!') }; React.render( , document.body )

    React.Children

    为处理 this.props.children 这个封闭的数据结构提供了有用的工具。它有如下几个方法:

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

    遍历子元素,映射为一个新的子元素集合(跟 ES5 的 Array.map 差不多):

            var Component = React.createClass({
                deal : function(child, index){
                    console.log(child, index);
                    return !!index && child;  //第一个li会被过滤掉,因为其索引为0
                },
                render : function() {
                    return (
                        
      {React.Children.map(this.props.children, this.deal)}
    ) } }); React.render( (
  • 0
  • 1
  • 2
  • ), document.body )

     

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

    遍历子元素,对每一个子元素执行回调,但不像上述的 map 那样最终返回一个新的集合(跟 ES5 的 Array.forEach 差不多):

            var Hello = React.createClass({
    
                render: function() {
                    React.Children.forEach(this.props.children, function(child){
                        console.log(child.props, child.key)
                    });
                    return 
    Hello {this.props.name}
    ; } }); React.render(
  • , document.body);
  •  

    3. React.Children.count(object children)

    返回子元素的总数:

            var Component = React.createClass({
                render : function() {
                    var nums = React.Children.count(this.props.children);
                    return (
    • 一共有{nums}个子元素
    • //3 {this.props.children}
    ) } }); React.render( (
  • 0
  • 1
  • 2
  • ), document.body )

     

    4. React.Children.only(object children)

    返回仅有的一个子元素,否则(没有子元素或超过一个子元素)报错且不渲染任何东西:

            var Hello = React.createClass({
                render: function() {
                    return 
    Hello {React.Children.only(this.props.children)}
    ; } }); React.render( World ! //会报错“onlyChild must be passed a children with exactly one child.” , document.body);

     

    话说这块其实我有些疑虑,明明可以直接使用数组的原生方法,比如 this.props.children.map/forEach ,也可以直接用 this.props.children.length 来获取总数,React 封装自己的遍历方法难道是为了polyfill IE8?

    在最后说个有趣的小例子。我们知道 React.Children.map 和 React.Children.forEach 是有第三个参数(可选,用于修改上下文this)的,但我们试着执行下方的例子发现它并没按照我们的预期生效:

            var obj = {
                num : 3
            };
    
            var Component = React.createClass({
                deal : function(){
                    console.log(this);  //it`s NOT obj
                },
                render : function() {
                    React.Children.forEach(this.props.children, this.deal, obj);
                    return (
      {this.props.children}
    ) } }); React.render( (
  • 0
  • 1
  • 2
  • ), document.body );

    打印出来的是 Component 的构造器。ok,软的不行玩硬的,我们试着加俩个 bind(obj),总不至于不行了吧:

            var obj = {
                num : 3
            };
    
            var Component = React.createClass({
                deal : function(){
                    console.log(this);  //it`s NOT obj
                },
                render : function() {
                    React.Children.forEach.bind(obj)(this.props.children, this.deal.bind(obj));
                    return (
      {this.props.children}
    ) } }); React.render( (
  • 0
  • 1
  • 2
  • ), document.body );

    结果真的是不行,改为 call 和 apply 也都扑街~ 卧槽我读书少别欺负我啊。

    后来去提 issue 询问下才知道 React.creactClass 会在后续调用自身方法时将 this 自动绑定到当前组件上,自然我们获取到的 this 总会是组件的构造器了。

    因此 React.Children.map 和 React.Children.forEach 的第三个参数只要不用于 React.creactClass 的内部属性方法,都会跑的好好滴:

            var Component = React.createClass({
                render : function() {
                    React.Children.forEach(this.props.children, function(){ //独立的回调
                        console.log(this);  //obj无误!
                    }, obj);
                    return (
      {this.props.children}
    ) } });

    顶层API先总结到这边,下篇文章总结下同样很重要的组件API,共勉~

    donate

    转载于:https://www.cnblogs.com/vajoy/p/4631292.html

    你可能感兴趣的:(javascript,数据结构与算法)