react組件的多種寫(xiě)法與演進(jìn) - 小結(jié)

文檔創(chuàng)建時(shí)間: 2018-10-25
本文轉(zhuǎn)載自:https://zhuanlan.zhihu.com/p/26216173

目前猜惋,react組件有三種寫(xiě)法崭倘,分別是ES5的createClass寫(xiě)法斩个,ES6的class寫(xiě)法亮垫,以及stateless(無(wú)狀態(tài)組件)寫(xiě)法讳推。

下面由淺入深的說(shuō)說(shuō)這三種寫(xiě)法析砸。涵蓋了生命周期琅攘,反向數(shù)據(jù)流垮庐,es6/7等知識(shí)。

一坞琴,原始的createClass寫(xiě)法

createClass是react組件最原始的寫(xiě)法哨查,最早學(xué)react的人,應(yīng)該都接觸過(guò)這種寫(xiě)法剧辐。
create寫(xiě)法是基于ES5寒亥,它實(shí)際上是React對(duì)象的一個(gè)頂層API,它只接受一個(gè)配置對(duì)象作為參數(shù)荧关,如下:

var React = require('react');
var ReactDOM = require('react-dom');
var AppComponent = React.createClass( {這是一個(gè)react組件配置對(duì)象} );

1,下面說(shuō)說(shuō)組件的配置對(duì)象

首先溉奕,這個(gè)配置對(duì)象必須有一個(gè)render()方法,并且render()方法必須返回由閉合標(biāo)簽包裹的html片段忍啤。
render()方法的作用在于渲染DOM腐宋。

var AppComponent = React.createClass({
     render: function(){
        return (
          <div>最外層必須是閉合標(biāo)簽</div>
        );
    }    
});

一個(gè)最為簡(jiǎn)單react組件就這樣完成了。這個(gè)組件只配置了一個(gè)render函數(shù)檀轨,你還可以有更多的配置胸竞。

react組件的調(diào)用也很簡(jiǎn)單:

<div>
 <AppComponent />   // 調(diào)用react組件
</div>

最終結(jié)果如下:

<div>
  <div> 返回值最外層必須是閉合標(biāo)簽  </div>
</div>

2,添加組件生命周期方法

react組件本身除了render()方法以外,還有諸多生命周期方法参萄。這些生命周期方法如下:

#初始化階段
getDefaultProps()     //組件創(chuàng)建的時(shí)候調(diào)用

getInitialState()    //組件掛載之前調(diào)用卫枝,定義state初始值

componentWillMount()    //組件即將被裝載、渲染到頁(yè)面上

componentDidMount()    //組件掛載后調(diào)用

#組件運(yùn)行階段
componentWillReceiveProps()    //組件將要接收新屬性的時(shí)候調(diào)用

shouldComponentUpdate()    // 組件接受到新屬性或者新?tīng)顟B(tài)的時(shí)候調(diào)用

componentWillUpdate() // 新屬性或state 更新前調(diào)用

componentDidUpdate()    // 更新完成后調(diào)用

# 組件銷(xiāo)毀階段

 componentWillUnmount()  // 組件銷(xiāo)毀之前調(diào)用

那么讹挎,這些生命周期方法是不是必須的呢校赤?

沒(méi)有一個(gè)是必須的,也就是說(shuō)是否使用筒溃,使用哪些生命周期方法马篮,全憑你自身需求來(lái)決定。

但通常你會(huì)用到下面這幾個(gè):

getInitialState()    // 定義你的初始state

componentDidMount()    // 在render()方法之后調(diào)用怜奖,也就是執(zhí)行這個(gè)方法前DOM已經(jīng)渲染完成浑测,此時(shí)可以使用這個(gè)方法來(lái)載入數(shù)據(jù),也就是發(fā)送ajax請(qǐng)求數(shù)據(jù)

那么,這些方法是如何應(yīng)用的呢迁央?

很簡(jiǎn)單掷匠,使用方法和render()方法一樣,在組件配置對(duì)象中定義即可岖圈。組件配置對(duì)象實(shí)際上就是一個(gè)組件屬性和方法的集合讹语。

接著上面的例子:

var AppComponent = React.createClass({
   getDefaultProps: function(){
      // 一些邏輯
   },
   getInitialState: function(){
      // 一些邏輯
   },
   componentWillMount: function(){
      // 一些邏輯
   },
   componentDidMount: function(){
       // 一些邏輯
   },
  componentWillReceiveProps: function(){
        // 一些邏輯
   },
  shouldComponentUpdate: function(){
      // 一些邏輯
   },

  ……

  render:function(){
      return (
       <div> 返回值最外層必須是閉合標(biāo)簽  </div>
     )
   }
})

至此,完成了一個(gè)略完整的組件蜂科。

為什么說(shuō)是略完整顽决?因?yàn)檫€沒(méi)有添加組件驗(yàn)證器,也就是propTypes导匣。

3才菠,添加組件驗(yàn)證器propTypes

propTypes是一個(gè)對(duì)象,主要用于驗(yàn)證傳入組件的props屬性是否符合你在propTypes對(duì)象中設(shè)定的類(lèi)型 ,如果不符合逐抑,組件會(huì)報(bào)錯(cuò)鸠儿。通常在開(kāi)發(fā)環(huán)境中使用。

下面我們來(lái)給組件添加驗(yàn)證器厕氨,在組件內(nèi)配置propTypes屬性即可进每。以上面的例子為例。

var AppComponent = React.createClass({
   propTypes: {
       data: React.PropTypes.array,     // 驗(yàn)證傳入的data是不是數(shù)組命斧,如果不是則會(huì)報(bào)錯(cuò)
    loadding: React.PropTypes.bool,  // 驗(yàn)證loadding是否為true
    loadData: React.PropTypes.func, // 驗(yàn)證loadData是否為函數(shù)類(lèi)型
   },
   getDefaultProps: function(){
      // 一些邏輯
   },
   getInitialState: function(){
      // 一些邏輯
   },

  ……

  render:function(){
      return (
       <div> 返回值最外層必須是閉合標(biāo)簽  </div>
     )
   }
})

于是田晚,組件驗(yàn)證器添加完成。

props屬性是如何傳入呢国葬?如下:

<AppComponent 
     data = []
     loadding = { true }
     loadData = { 函數(shù) }
 />

所有傳入的屬性都可以在組件內(nèi)通過(guò)this.props對(duì)象訪問(wèn)到贤徒。

4,自定義方法

上面講解了react組件自帶的一些方法和屬性。那么除了組件自帶的汇四,我們可不可以給組件自定義我們需要的方法呢接奈?

答案必然是肯定的。光自帶的方法是無(wú)法滿足需求的通孽,往往我們需要自定義一些方法來(lái)處理很多的邏輯序宦。

自定義方法和組件自帶方法一樣,都是在組件配置對(duì)象內(nèi)定義背苦。以上面的粟子互捌,再來(lái)舉個(gè)粟子:

var AppComponent = React.createClass({
   propTypes: {
       data: React.PropTypes.array,     // 驗(yàn)證傳入的data是不是數(shù)組,如果不是則會(huì)報(bào)錯(cuò)
    loadding: React.PropTypes.bool,  // 驗(yàn)證loadding是否為true
    loadData: React.PropTypes.func, // 驗(yàn)證loadData是否為函數(shù)類(lèi)型
   },

   getInitialState:  function(){
      // 一些邏輯
   },
   componentDidMount: function(){
       // ajax請(qǐng)求
   },
   renderSubmit: function(e){    // 自定義的方法行剂,用于處理表單提交
      e. stopPropagation();
      // 一些表單提交處理邏輯
   }
  ……

  render:function(){
      return (
       <div> 
          <form method="post",action="/api/query" onSubmit={this.renderSubmit.bind(this)}>   // 調(diào)用自定義方法

         </form>
       </div>
     )
   }
})

至此秕噪,一個(gè)完整的組件基本完成。

createClass方法的劣勢(shì)

現(xiàn)階段已不推薦使用createClass方法來(lái)創(chuàng)建組件厚宰,準(zhǔn)確地說(shuō)它已經(jīng)過(guò)時(shí)了腌巾。

  • 基于es5,終究是要被淘汰的

  • 過(guò)于臃腫,組件性能略差

二壤躲,class組件寫(xiě)法城菊,也就是使用es6的寫(xiě)法

1备燃,創(chuàng)建class組件

class寫(xiě)法是目前比較推薦的寫(xiě)法碉克,另一種最為推薦的寫(xiě)法是stateless組件,后面會(huì)講到并齐。

這里所說(shuō)的class是es6的class特性漏麦。

react巧妙地運(yùn)用了這一特性。因?yàn)樗幸粋€(gè)非常棒的API况褪,那就是extends(繼承)撕贞。

我們先來(lái)回顧下如何使用class定義一個(gè)類(lèi),如下:

class  AppComponent { }

這樣就定義了一個(gè)AppComponent類(lèi)测垛。

再來(lái)回顧下捏膨,如何繼承另一個(gè)類(lèi),如下:

 class  AppComponent extends APP { }

這樣AppComponent類(lèi)就繼承了APP類(lèi)食侮,AppComponent就可以訪問(wèn)到APP類(lèi)的屬性和方法号涯。

總所周知,react有一個(gè)頂層組件锯七,也就是React.Component链快,它本身封裝了諸多屬性和方法,那么眉尸,我們可以使用class來(lái)繼承它域蜗,從而使它的屬性和方法能夠共享給我們自定義的一個(gè)類(lèi),從而形成一個(gè)新的組件噪猾。如下:

import React  from 'react';

 class AppComponent extends  React.Component {   // 定義一個(gè)繼承于react頂層Component的新組件AppComponent

     constructor(props){
        super(props)            // 調(diào)用super父類(lèi)構(gòu)造函數(shù)改變this指向
     }

     //這是一個(gè)基于es6的react組件 

   render(){      
       return  <div> 
            返回值最外層必須是閉合標(biāo)簽  
      </div>
   }
}

或者

 import React,{ Component }  from 'react';   // 解構(gòu)

 class AppComponent extends  Component {   // 定義一個(gè)繼承于react頂層Component的新組件AppComponent

    constructor(props){
        super(props)            // 調(diào)用super父類(lèi)構(gòu)造函數(shù)改變this指向
     }

     //這是一個(gè)基于es6的react組件 

    render(){      
       return  <div> 
            返回值最外層必須是閉合標(biāo)簽  
      </div>
   }
}

# 上面兩種寫(xiě)法同理霉祸,只是第二種使用了es6的另一個(gè)特性,對(duì)象的解構(gòu)袱蜡,將Component從React對(duì)象中解構(gòu)出來(lái)丝蹭。

至此,一個(gè)基于es6的react組件誕生了戒劫。

2半夷,class組件與createClass組件的比較

class組件的用法和createClass組件的用法基本一致,它同樣有生命周期迅细,有驗(yàn)證器巫橄,同樣可以自定義方法等等。

createClass組件到class組件的變遷茵典,實(shí)際上是es5到es6的變遷湘换,基本上是語(yǔ)法上的變遷和功能上的拓展。組件的本質(zhì)是沒(méi)有改變的,只是寫(xiě)法稍有不同彩倚。

下面來(lái)說(shuō)說(shuō)這些不同點(diǎn)筹我。

創(chuàng)建組件的方式不同

一個(gè)是使用es5封裝的createClass方法來(lái)創(chuàng)建,一個(gè)是使用es6的class特性來(lái)創(chuàng)建帆离。

上面已經(jīng)詳細(xì)闡述過(guò)蔬蕊,這點(diǎn)就不過(guò)多闡述了。

定義初始state的方式不同

createClass組件是使用getInitialState方法來(lái)定義初始state的哥谷,如下:

 var AppComponent = React.createClass({

     getInitialState: function(){
        return {
            loadding: false,
            isshow: false,
            data: null
            ……
      }       
    } 

 })

class組件定義初始state則大不相同岸夯,可分為兩種,如下:

# 第一種们妥,構(gòu)造函數(shù)內(nèi)定義猜扮,這是es6的實(shí)現(xiàn)
class AppComponent extends  React.Component {

   constructor(props){
      super(props);     // 調(diào)用父類(lèi)的構(gòu)造函數(shù),改變this指向
       this.state = {
         loadding: false,
         isshow: false,
         data: null,
         ……
      }
   }

   ……
}
# 第二種监婶,直接定義靜態(tài)屬性旅赢,這是es7的實(shí)現(xiàn),更為簡(jiǎn)單,實(shí)用
class AppComponent extends  React.Component {

   state = {
        loadding: false,
        isshow: false,
        data: null
       ……
   }

    ……

}

# es6規(guī)定是只有靜態(tài)方法惑惶,沒(méi)有靜態(tài)屬性的煮盼。但是es7可以定義靜態(tài)屬性,可通過(guò)babel轉(zhuǎn)換實(shí)現(xiàn)集惋。
# 要使用es7也很簡(jiǎn)單孕似,通常安裝和配置babel-preset-stage-0即可使用所有的es6/7新特性

react組件內(nèi)es5和es6的不同寫(xiě)法

直接舉個(gè)粟子說(shuō)明,以class組件為例:

# es5寫(xiě)法

class AppComponent extends  React.Component {

   componentDidMount: function(){

   }
   renderSubmit: function(){

  }

  ……

  render: function(){

    return <div> hello </div>
  }

}

# es6寫(xiě)法刮刑,有2種

// 寫(xiě)法一
class AppComponent extends  React.Component {

    ……

    componentDidMount(){

    }
    renderSubmit(){

   }

   ……

  render(){

   return <div> hello </div>

  }

}

/*
  提示: 
  componentDidMount(){

   }
 這種寫(xiě)法相當(dāng)于es5的:
 componentDidMount: function(){

 }

*/


# 寫(xiě)法二喉祭,使用箭頭函數(shù),似乎高逼格一些  
class AppComponent extends  React.Component {

     …… 

    componentDidMount=()=>{

    }
    renderSubmit=()=>{

    }

   ……

  render=()=>{
     return <div> hello </div>
  }
}

# 提示: class嚴(yán)格來(lái)講不是一個(gè)對(duì)象雷绢,class內(nèi)定義的屬性和方法并不需要用逗號(hào)','隔開(kāi)泛烙。

三, stateless組件寫(xiě)法

前言

所謂stateless組件翘紊,也就是無(wú)狀態(tài)組件蔽氨。 這種react組件有一個(gè)特點(diǎn),它沒(méi)有生命周期方法帆疟,沒(méi)有render方法鹉究,連state也沒(méi)有,this也沒(méi)有,也不需要實(shí)例化踪宠。

為什么需要這樣的組件自赔?

很多時(shí)候,從業(yè)務(wù)上考慮柳琢,我們的某些組件只用于純UI展示绍妨,并沒(méi)有涉及到生命周期润脸,也不需要setState, 但是react組件本身依然存在生命周期方法等一大堆組件本身的設(shè)定,然而這些設(shè)定我們根本不需要用到的他去,它們的存在造成了資源浪費(fèi)毙驯,多余,和臃腫灾测。 另外組件實(shí)例化是需要占用內(nèi)存爆价,消耗性能的。

因此行施,考慮到不同業(yè)務(wù)需求允坚,后來(lái)react增加了stateless組件的支持魂那。

stateless組件本質(zhì)是一個(gè)函數(shù)蛾号,它沒(méi)有生命周期,也不需要實(shí)例化涯雅,沒(méi)有this指向, 更輕盈鲜结,性能更加好。

這種組件是所有react組件中性能最好的組件類(lèi)型活逆。官方也推薦多用這種組件精刷。

stateless組件的定義

stateless組件本質(zhì)是一個(gè)帶有返回值的函數(shù),而且必須是使用閉合標(biāo)簽包裹的返回值蔗候。 下面來(lái)舉個(gè)粟子:

const AppComponent = (props) =>{

     // 一些邏輯

     return <div>
      這是一個(gè)干凈純潔的stateless組件
     </div>
  }

這樣就定義了一個(gè)常見(jiàn)的stateless組件怒允。發(fā)現(xiàn)沒(méi),這就是一個(gè)函數(shù)锈遥。 有沒(méi)有覺(jué)得非常干凈纫事,整潔,高逼格了許多所灸?

stateless組件的使用和前面兩種是一樣的丽惶,直接來(lái)個(gè)粟子:

<div>
  <AppComponent />
 </div>

同樣,你還可以給它加驗(yàn)證器:

AppComponent.propTypes = {
    data: React.PropTypes.array,     // 驗(yàn)證傳入的data是不是數(shù)組爬立,如果不符合則會(huì)報(bào)錯(cuò)
    loadding: React.PropTypes.bool,  // 驗(yàn)證傳入的loadding是否為true
    loadData: React.PropTypes.func, // 驗(yàn)證傳入的loadData是否為函數(shù)類(lèi)型
 }

如何獲取props屬性钾唬?
首先來(lái)看看如何在調(diào)用組件時(shí)傳入props屬性:

<div>
  <AppComponent 
   data = {[]}
   loadding = { true }
   loadData = { 函數(shù) }
  />
 </div>

上面組件調(diào)用時(shí)傳入了data, loadding, loadData三個(gè)props屬性。這些傳入的屬性最終都會(huì)被收集到組件的props對(duì)象里面侠驯。

需要注意的是,stateless組件的props是通過(guò)傳參傳進(jìn)去的抡秆,因?yàn)樗旧硎且粋€(gè)函數(shù),沒(méi)有this

而獲取props屬性的方式也五花八門(mén)吟策,下面直接看個(gè)粟子:

 # 第一種儒士,在內(nèi)部展開(kāi)獲取
 const AppComponent = (props) =>{

     const { data, loadding, loadData } = props; // 通過(guò)es6的對(duì)象解構(gòu)賦值的寫(xiě)法,直接從props獲取到
    /*
     上面等同于:
     const data = props.data;
     const loadding = props.loadding;
     const loadData = props.loadData;
    */

     ……

     return <div>
      這是一個(gè)干凈純潔的stateless組件
     </div>
  }

  # 第二種踊挠,高逼格一些乍桂,直接從參數(shù)里解構(gòu)出來(lái)冲杀,如下:
  const AppComponent = ({ data, loadding, loadData }) =>{

     ……

     return <div>
      這是一個(gè)干凈純潔的stateless組件
     </div>
  }

  或者,如果參數(shù)較多睹酌,可以寫(xiě)得優(yōu)雅一些:

  const AppComponent = ({ 
    data, 
    loadding, 
    loadData
  }) =>{

     ……

     return <div>
      這是一個(gè)干凈純潔的stateless組件
     </div>
  }

使用反向數(shù)據(jù)流來(lái)實(shí)現(xiàn)setState功能

stateless組件本身沒(méi)有生命周期权谁,也無(wú)法設(shè)置state,那是否意味著stateless組件不能使用setState功能呢憋沿? 答案是可以實(shí)現(xiàn),不過(guò)是間接使用旺芽。實(shí)現(xiàn)的方式是——反向數(shù)據(jù)流。 有兩個(gè)前提條件辐啄,一個(gè)是必須依賴(lài)一個(gè)父組件采章,二是這個(gè)父組件不是stateless組件,它有生命周期壶辜。

在實(shí)踐之前悯舟,我們先來(lái)解決一個(gè)疑問(wèn),react明明是單向綁定砸民,何來(lái)反向數(shù)據(jù)流抵怎? 的確react本身是單向綁定,是自上而下傳遞信息的岭参,也就是從父組件傳遞給子組件反惕,逐級(jí)向下傳遞。 如果要實(shí)現(xiàn)反向數(shù)據(jù)流演侯,那么就意味著要實(shí)現(xiàn)自下而上傳遞信息姿染,也就是要實(shí)現(xiàn)子組件向父組件傳遞信息。 那么秒际,如何做到子組件向父組件傳遞信息悬赏?

下面是實(shí)現(xiàn)原理: 在父組件中定義一個(gè)方法,把這個(gè)方法傳遞給子組件程癌,由子組件去觸發(fā)這個(gè)方法舷嗡,并且以函數(shù)傳參的方式,把需要的信息傳遞給父組件嵌莉。 這樣就實(shí)現(xiàn)了自下而上傳遞的反向數(shù)據(jù)流进萄。

那么,我們可以使用這個(gè)原理來(lái)實(shí)現(xiàn)stateless組件的setState功能锐峭。 下面來(lái)個(gè)例子:

# 父組件
  import ChildComponent from './ChildComponent'; // 引入子組件
  class AppComponent extends React.Component {
   state = {
     msg:null,
     content: null   // 初始狀態(tài)
   }
   changeLoad(content){  // 這個(gè)方法是傳遞給子組件調(diào)用的中鼠,并且子組件會(huì)傳遞content過(guò)來(lái)
     this.setState({
      msg: '反向傳遞成功',
      content           // { content } 等同于 { content: content }
     })
   }
   render(){
     return <div>
      { this.state.content }
      <div>
       <ChildComponent,
        msg = { msg }                   
        changeLoad = { this.changeLoad }   // 調(diào)用子組件并傳遞msg以及changeLoad方法
       />
      </div>
     </div>
   }
 }

# 子組件
const ChildComponent =({ msg, changeLoad })=>{

  const str = "我是一段文字,子組件把我這段文字傳給了它的父組件沿癞,并在父組件中展示我";
  return <div>
   { msg?msg:null }  
   <button onClick = { changeLoad(str) }> 點(diǎn)我傳遞str給父組件 </button>  // 調(diào)用父組件的changeLoad方法并傳遞str給父組件
  </div>
}

這個(gè)例子很簡(jiǎn)單援雇。父組件定義了msg和content兩個(gè)初始state, 并且定義了一個(gè)changeLoad函數(shù),這個(gè)函數(shù)是傳遞給子組件椎扬,由子組件去觸發(fā)的惫搏。 子組件觸發(fā)的時(shí)候傳遞新的content給父組件, changeLoad函數(shù)接受到新的content就會(huì)通過(guò)setState功能去更新舊的content具温,以及msg提示。 此時(shí)父組件就會(huì)展示子組件傳遞過(guò)來(lái)的content筐赔,并傳遞msg通知子組件铣猩。msg就是被改變的props屬性。 這樣不僅實(shí)現(xiàn)了正向傳遞茴丰,也實(shí)現(xiàn)了反向傳遞达皿。

四,不同組件的最佳應(yīng)用方式

寫(xiě)react組件贿肩,推薦使用class組件和stateless組件峦椰。createClass組件盡量少用或者不用。 下面來(lái)說(shuō)說(shuō)這三種組件的應(yīng)用場(chǎng)景汰规。

createClass

已不推薦使用汤功,這里不再多講。但你仍需要了解它控轿,因?yàn)槟憧赡軙?huì)接觸到一些舊項(xiàng)目冤竹,或者一些舊的開(kāi)源項(xiàng)目,這些項(xiàng)目大都采用createClass寫(xiě)法拧额。 再加上es6受限于兼容性問(wèn)題而尚未普及槐沼,所以你可能接觸到較多的createClass組件,你有必要去了解它。

class組件和stateless組件互為替補(bǔ)

這兩種組件通常要搭配使用剩彬,互為替補(bǔ),這是react組件最好的應(yīng)用方式漾狼。

在實(shí)踐前乎婿,先來(lái)講講兩個(gè)概念,分別是——容器組件票唆,展示組件朴读。 也就是Container Component和 Presentational Component

所謂Container Component(容器組件),簡(jiǎn)單來(lái)講就是它通常是作為一個(gè)父組件走趋,它底下領(lǐng)著一群子組件衅金。容器組件(父組件)的作用在于,給子組件傳遞數(shù)據(jù)簿煌,并且定義邏輯方法傳遞給子組件氮唯。 子組件不參與或少參與業(yè)務(wù)邏輯處理,它主要負(fù)責(zé)接收和展示容器組件傳遞過(guò)來(lái)的數(shù)據(jù)姨伟,以及調(diào)用傳遞過(guò)來(lái)的邏輯方法惩琉。 而這里所說(shuō)的子組件,通常就是展示型組件夺荒,也就是Presentational Component瞒渠。
這里為什么說(shuō)class組件和stateless組件搭配使用良蒸,互為替補(bǔ),是react組件的最好應(yīng)用方式呢伍玖?

首先诚啃,stateless組件沒(méi)有生命周期,無(wú)實(shí)例化私沮,性能最好始赎。而展示組件通常只需要做數(shù)據(jù)展示,和邏輯方法調(diào)用仔燕,它并不需要使用到生命周期方法造垛。 這不正和stateless組件最為契合嗎? 于是晰搀,stateless組件五辽,通常用作于展示組件。

再來(lái)說(shuō)說(shuō)class組件外恕,它有生命周期杆逗,再搭配es6/7語(yǔ)法,它可以處理眾多復(fù)雜的業(yè)務(wù)邏輯鳞疲。 而容器組件通常只專(zhuān)注于處理業(yè)務(wù)邏輯罪郊,需要使用生命周期,對(duì)于數(shù)據(jù)的展示則交給展示組件尚洽。這正和class組件最為契合悔橄。于是,通常class組件作為容器組件腺毫。

這兩種組件癣疟,各自分工,互為替補(bǔ)潮酒,是react組件最好的應(yīng)用方式睛挚。

下面是一個(gè)例子:

# 容器組件
// /containers/index.js

import ListTableComponent from '/components/ListTable';
import ItemTableComponent from '/components/ItemTable';

class AppComponent extends React.Component {

   state = {
        loadding: false
   }


render =()=>{

   const { list, item } = this.props;  

   const handdleLoad = ()=>{

     // ToDo
  }

   const listProps = { list, handdleLoad }; 

   const  itemProps = { item, handdleLoad }; 

   return <div className="box">

      <ListTableComponent       // 子組件
       { ...listProps }                // ‘...’ 是es7的展開(kāi)屬性運(yùn)算符,
      />

      <ItemTableComponent    // 子組件
       { ...itemProps }
     />

   </div>
 }
}

# 展示組件一 
//  /components/ListTable.js

const ListTable = ({ list,handdleLoad })=>{


   return <div>

           ……
           <td> {list.coutry} </td>
           <td> {list.address} </td>
          ……

      <button onClick={ handdleLoad() }> 做一些事情 </button>
    </div>
}

# 展示組件二
//  /components/ItemTable.js

const ItemTable = ({ item,handdleLoad })=>{


   return <div>

           ……
           <td> {item.name} </td>
           <td> {item.age} </td>
          ……

      <button onClick={ handdleLoad() }> 做一些事情 </button>
    </div>
}

這個(gè)例子中急黎,容器組件index.js載入了兩個(gè)子組件扎狱,這兩個(gè)是展示組件,容器組件定義了handdleLoad方法叁熔,并從props拿到數(shù)據(jù)list和item兩個(gè)數(shù)據(jù)源委乌,再組織成listProps和itemProps兩個(gè)props屬性對(duì)象,并把他們分別傳給ListTable和ItemTable兩個(gè)展示組件荣回。 這兩個(gè)展示組件從props中拿到傳過(guò)來(lái)的數(shù)據(jù)遭贸,并在render方法中展示出來(lái),并不需要處理過(guò)多業(yè)務(wù)邏輯心软。

總結(jié)

react組件的演進(jìn)壕吹,依賴(lài)于js語(yǔ)法的演進(jìn)著蛙,隨著es6/7的到來(lái),react組件的寫(xiě)法變得多樣耳贬,且更為高效便捷踏堡。 因此,多結(jié)合es6/7語(yǔ)法咒劲,多使用stateless組件顷蟆,可使你的react應(yīng)用更上一層樓。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末腐魂,一起剝皮案震驚了整個(gè)濱河市帐偎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蛔屹,老刑警劉巖削樊,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異兔毒,居然都是意外死亡漫贞,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)育叁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)迅脐,“玉大人,你說(shuō)我怎么就攤上這事擂红∫羌剩” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵昵骤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我肯适,道長(zhǎng)变秦,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任框舔,我火速辦了婚禮蹦玫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刘绣。我一直安慰自己樱溉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布纬凤。 她就那樣靜靜地躺著福贞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪停士。 梳的紋絲不亂的頭發(fā)上挖帘,一...
    開(kāi)封第一講書(shū)人閱讀 49,806評(píng)論 1 290
  • 那天完丽,我揣著相機(jī)與錄音,去河邊找鬼拇舀。 笑死逻族,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的骄崩。 我是一名探鬼主播聘鳞,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼要拂!你這毒婦竟也來(lái)了抠璃?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤宇弛,失蹤者是張志新(化名)和其女友劉穎鸡典,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體枪芒,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡彻况,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舅踪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纽甘。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖抽碌,靈堂內(nèi)的尸體忽然破棺而出悍赢,到底是詐尸還是另有隱情,我是刑警寧澤货徙,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布左权,位于F島的核電站,受9級(jí)特大地震影響痴颊,放射性物質(zhì)發(fā)生泄漏赏迟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一蠢棱、第九天 我趴在偏房一處隱蔽的房頂上張望锌杀。 院中可真熱鬧,春花似錦泻仙、人聲如沸糕再。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)突想。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蒿柳,已是汗流浹背饶套。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留垒探,地道東北人妓蛮。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像圾叼,于是被迫代替她去往敵國(guó)和親蛤克。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容