React:复合组件

2018-06-19 11:06 更新
      在传统的HTML中,元素是构成页面的基础单位。而在React中,构建页面的基础单元是React组件。

我们也可以把React组件看成是混入了JavaScript表达能力的HTML元素。实际上,写React组件主要就是构建组件。
本质上,一个组件就是一个JavaScript函数,它接受属性(props)和状态(state)作为参数,并输出渲染好的HTML。

React的复合(composition)能力允许我们通过结合小巧的、简单的组件和数据对象,来构造大而复杂的组件。

注意:React组件并不具备扩展性,而是通过组件之间的组合来构建应用。

组合实例

一起来使用 Facebook Graph API 开发显示个人图片和用户名的简单 Avatar 组件吧。

var ProfilePic = React.createClass({   

  render: function() {   

    return (   

      <img src={'http://graph.facebook.com/' + this.props.username + '/picture'} />   

    );   

  }  

});   


var ProfileLink = React.createClass({

 render: function() {   

   return (   

     <a href={'http://www.facebook.com/' + this.props.username}>   

      {this.props.username}   

     </a>   

   );   

 }  

});   


var Avatar = React.createClass({      

  render: function() {      

    return (      

      <div>      

         <ProfilePic username={this.props.username} />      

         <ProfileLink username={this.props.username} />      

      </div>      

    );      

  }    

});


ReactDOM.render(   

  <Avatar username="pwh" />,   

  document.body  

);

在上面的代码中,avatar组件由两个组件(PropfilePic和ProfileLink)组合而成。
a和img是HTML的基本元素,我们可以直接使用。组件的层从上往下看是这样的:
Avatar → PropfilePic → img
Avatar → ProfileLink → a
这里的箭头表示“有一个”。Avatar组件“有一个”图片组件PropfilePic,PropfilePic“有一个”图片元素img。这就是组合模式(composition pattern)的特征。

父组件、子组件关系
子组件与其父组件通信的最简单方式就是使用属性(props)。父组件需要通过属性传入一个回调函数,子组件在需要时进行调用。

 var MyCheckbox = React.createClass({   

  handleChange: function(event){   

    var checked = event.target.checked;   

    this.props.onChanged(checked);   

  },   

  render: function(){   

    return (   

      <label htmlFor="check1">   

        <input type="checkbox" id="check1" name="" onChange={this.handleChange}/>   

        选我   

      </label>   

    );   

  }   

});

       

var MyForm = React.createClass({      

  handleChange: function(value){      

    if(value){      

      console.log('被选中了');      

    }else{      

      console.log('取消选中');      

    }      

  },      

  render: function(){      

    return (      

      <div className="form-group">      

        <MyCheckbox onChanged={this.handleChange}/>      

      </div>      

    );      

  }     

});


ReactDOM.render(   

  <MyForm />,   

  document.body   

);

上面的代码中,我们将MyCheckbox组件中的handleChange方法绑定到input元素的change事件监听器上,然后在MyFrom组件里同样添加一个handleChange方法,将它传递给MyCheckbox组件。

当input监听到用户更改时,就把状态checked值传递给父组件。

子级
在React中,我们能通过一个特殊的属性this.props.children来获取子级,即父组件的所有子节点。

var Parent = React.createClass({   

  render: function(){   

    return (   

      <div>   

        {this.props.children}   

      </div>   

    );   

  }   

});       


ReactDOM.render(   

  <Parent><p>123</p></Parent>,   

  document.body   

);


//渲染结果

<div>

  <p>123</p>

</div>


注意:this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。

不过,我们可以通过 React.Children 工具类来操作,就不需考虑这些了。

React.Children工具类共有四个方法:

React.Children.map、React.Children.forEach、React.Children.count、React.Children.only


(1)React.Children.map

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

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

var Parent = React.createClass({   

  render: function(){   

    return (   

      <div>   

         {   

           React.Children.map(this.props.children,function(item,i){   

             return item;   

           })   

         }   

      </div>   

   );   

 }   

});


ReactDOM.render(   

  <Parent>

    <p>1</p>

    <p>2</p>

  </Parent>,   

  document.body   

);


//渲染结果

<div>

  <p>1</p>

  <p>2</p>

</div>


(2)React.Children.forEach

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

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


(3)React.Children.count

React.Children.count(object children)

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


(4)React.Children.only

React.Children.only(object children)

返回 children 中仅有的子级。否则抛出异常。这里仅有的子级,only方法接受的参数只能是一个对象,不能是多个对象(数组)。


总结

  • 在React中,构建页面的基础单元是React组件。写React组件主要就是构建组件。
  •  React的复合(composition)能力允许我们通过结合小巧的、简单的组件和数据对象,来构造大而复杂的组件。
  •  子组件与其父组件通信的最简单方式就是使用属性(props)。父组件需要通过属性传入一个回调函数,子组件在需要时进行调用。
  • 可以使用React.children工具栏去操作this.props.children(子节点)



以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号