React:復(fù)合組件

2018-06-19 11:06 更新
      在傳統(tǒng)的HTML中,元素是構(gòu)成頁面的基礎(chǔ)單位。而在React中,構(gòu)建頁面的基礎(chǔ)單元是React組件。

我們也可以把React組件看成是混入了JavaScript表達(dá)能力的HTML元素。實(shí)際上,寫React組件主要就是構(gòu)建組件。
本質(zhì)上,一個組件就是一個JavaScript函數(shù),它接受屬性(props)和狀態(tài)(state)作為參數(shù),并輸出渲染好的HTML。

React的復(fù)合(composition)能力允許我們通過結(jié)合小巧的、簡單的組件和數(shù)據(jù)對象,來構(gòu)造大而復(fù)雜的組件。

注意:React組件并不具備擴(kuò)展性,而是通過組件之間的組合來構(gòu)建應(yīng)用。

組合實(shí)例

一起來使用 Facebook Graph API 開發(fā)顯示個人圖片和用戶名的簡單 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)的特征。

父組件、子組件關(guān)系
子組件與其父組件通信的最簡單方式就是使用屬性(props)。父組件需要通過屬性傳入一個回調(diào)函數(shù),子組件在需要時進(jìn)行調(diào)用。

 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事件監(jiān)聽器上,然后在MyFrom組件里同樣添加一個handleChange方法,將它傳遞給MyCheckbox組件。

當(dāng)input監(jiān)聽到用戶更改時,就把狀態(tài)checked值傳遞給父組件。

子級
在React中,我們能通過一個特殊的屬性this.props.children來獲取子級,即父組件的所有子節(jié)點(diǎn)。

var Parent = React.createClass({   

  render: function(){   

    return (   

      <div>   

        {this.props.children}   

      </div>   

    );   

  }   

});       


ReactDOM.render(   

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

  document.body   

);


//渲染結(jié)果

<div>

  <p>123</p>

</div>


注意:this.props.children 的值有三種可能:如果當(dāng)前組件沒有子節(jié)點(diǎn),它就是 undefined ;如果有一個子節(jié)點(diǎn),數(shù)據(jù)類型是 object ;如果有多個子節(jié)點(diǎn),數(shù)據(jù)類型就是 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 參數(shù)中的)上調(diào)用 fn 函數(shù),此函數(shù)中的 this 指向 上下文。如果 children 是一個內(nèi)嵌的對象或者數(shù)組,它將被遍歷:不會傳入容器對象到 fn 中。如果 children 參數(shù)是 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   

);


//渲染結(jié)果

<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 當(dāng)中的組件總數(shù),和傳遞給 map 或者 forEach 的回調(diào)函數(shù)的調(diào)用次數(shù)一致。


(4)React.Children.only

React.Children.only(object children)

返回 children 中僅有的子級。否則拋出異常。這里僅有的子級,only方法接受的參數(shù)只能是一個對象,不能是多個對象(數(shù)組)。


總結(jié)

  • 在React中,構(gòu)建頁面的基礎(chǔ)單元是React組件。寫React組件主要就是構(gòu)建組件。
  •  React的復(fù)合(composition)能力允許我們通過結(jié)合小巧的、簡單的組件和數(shù)據(jù)對象,來構(gòu)造大而復(fù)雜的組件。
  •  子組件與其父組件通信的最簡單方式就是使用屬性(props)。父組件需要通過屬性傳入一個回調(diào)函數(shù),子組件在需要時進(jìn)行調(diào)用。
  • 可以使用React.children工具欄去操作this.props.children(子節(jié)點(diǎn))



以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號