九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
一文詳解 React 組件類型

腳本之家

你與百萬開發(fā)者在一起

本文的目標(biāo)是讓開發(fā)者清晰地了解 React 組件類型,哪些在現(xiàn)代 React 應(yīng)用中依然在使用,以及為何一些類型現(xiàn)在不再使用了。

作者 | Robin Wieruch

譯者 | 彎月

責(zé)編 | 屠敏

出品 | CSDN(ID:CSDNNews)

以下為譯文:

盡管React從2013年發(fā)布到現(xiàn)在并沒有引入太多重大改變,但不同類型的React組件也出現(xiàn)了不少。一些組件類型和組件設(shè)計(jì)模式今天依然在使用,它們已成了構(gòu)建React應(yīng)用程序的標(biāo)準(zhǔn),而另一些類型的組件只會(huì)在舊的應(yīng)用和新手教學(xué)中出現(xiàn)。

在這篇文章中,我想通過層次化的方式向初學(xué)React的人介紹一下不同的React組件和React設(shè)計(jì)模式。讀完本文后,你應(yīng)當(dāng)能夠從舊的應(yīng)用和入門文章中分辨出不同類型的React組件,并能夠自信地編寫自己的現(xiàn)代React組件。

01

React createClass組件

我們要從React的createClass組件說起。createClass方法為開發(fā)者提供了一個(gè)工廠方法,無需編寫JavaScript類就可以創(chuàng)建React類組件。在JavaScript ES6出現(xiàn)之前,這種方法是創(chuàng)建React組件的標(biāo)準(zhǔn)方法,因?yàn)樵贘avaScript ES5時(shí)代還無法使用類語法:

var App = React.createClass({
  getInitialState: function() {
    return {
      value: '',
    };
  },

  onChange: function(event) {
    this.setState({ value: event.target.value });
  },

  render: function() {
    return (
      <div>
        <h1>Hello React 'createClass' Component!</h1>

        <input
          value={this.state.value}
          type='text'
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  },
});

createClass()工廠方法接受一個(gè)對象,該對象定義了React組件中的方法。其中,getInitialState()方法用來設(shè)置React組件的初始狀態(tài),還有必須的render()方法用來顯示JSX形式的組件。給對象傳遞更多函數(shù)即可添加更多的“方法”(如onChange())。

還可以使用生命周期方法來管理副作用。例如,為了隨時(shí)將輸入框中的值保存到瀏覽器的local storage中,可以利用componentDidUpdate()這個(gè)生命周期方法,只需要將該函數(shù)傳遞給工廠函數(shù)的對象即可。而且,local storage中的值也可以在組件接收初始狀態(tài)的時(shí)候讀出來:

var App = React.createClass({
  getInitialState: function() {
    return {
      value: localStorage.getItem('myValueInLocalStorage') || '',
    };
  },

  componentDidUpdate: function() {
    localStorage.setItem('myValueInLocalStorage', this.state.value);
  },

  onChange: function(event) {
    this.setState({ value: event.target.value });
  },

  render: function() {
    return (
      <div>
        <h1>Hello React 'createClass' Component!</h1>

        <input
          value={this.state.value}
          type='text'
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  },
});

每次重新加載或刷新瀏覽器時(shí),之前在輸入框中輸入過的、保存在local storage中的初始狀態(tài)就會(huì)在組件初次mount的時(shí)候顯示出來。

注意:React的createClass方法現(xiàn)在已經(jīng)不在React的核心包中了。如果你想嘗試下,就必須要安裝另一個(gè)包:npm install create-react-class。

React Mixin

React Mixin是在React提出可重用組件邏輯的高級設(shè)計(jì)方式時(shí)加入的。利用Mixin可以將React組件中的邏輯提取出來作為獨(dú)立的對象使用。在使用Mixin對象時(shí),Mixin中的所有功能都會(huì)被引入到組件中:

var localStorageMixin = {
  getInitialState: function() {
    return {
      value: localStorage.getItem('myValueInLocalStorage') || '',
    };
  },

  setLocalStorage: function(value) {
    localStorage.setItem('myValueInLocalStorage', value);
  },
};

var App = React.createClass({
  mixins: [localStorageMixin],

  componentDidUpdate: function() {
    this.setLocalStorage(this.state.value);
  },

  onChange: function(event) {
    this.setState({ value: event.target.value });
  },

  render: function() {
    return (
      <div>
        <h1>Hello React 'createClass' Component with Mixin!</h1>

        <input
          value={this.state.value}
          type='text'
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  },
});

在這個(gè)例子中,Mixin提供了組件的初始狀態(tài),而該初始狀態(tài)是從local storage中讀取的,并且還利用setLocalStorage()擴(kuò)展原來的組件,該函數(shù)之后會(huì)在組件中被調(diào)用。為了讓Mixin更靈活,我們可以使用一個(gè)返回函數(shù)的對象:

function getLocalStorageMixin(localStorageKey) {
  return {
    getInitialState: function() {
      return { value: localStorage.getItem(localStorageKey) || '' };
    },

    setLocalStorage: function(value) {
      localStorage.setItem(localStorageKey, value);
    },
  };
}

var App = React.createClass({
  mixins: [getLocalStorageMixin('myValueInLocalStorage')],

  ...
});

不過,現(xiàn)代React應(yīng)用程序已經(jīng)不再使用Mixin了,因?yàn)樗鼈儠?huì)帶來一些負(fù)面作用。關(guān)于Mixin的細(xì)節(jié)和消亡過程可以閱讀這里(https://reactjs.org/blog/2016/07/13/mixins-considered-harmful.html)

02

React類組件

React類組件是在JavaScript ES6時(shí)引入的,因?yàn)橹钡紼S6才支持JS類。有時(shí)候它們也被稱為React ES6類組件。至少有了JavaScript ES6之后,就不需要使用React的createClass方法了。JS自己終于支持類了:

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      value: '',
    };

    this.onChange = this.onChange.bind(this);
  }

  onChange(event) {
    this.setState({ value: event.target.value });
  }

  render() {
    return (
      <div>
        <h1>Hello React ES6 Class Component!</h1>

        <input
          value={this.state.value}
          type='text'
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  }
}

使用JavaScript類編寫的React Component有個(gè)類似于類構(gòu)造器的方法,主要用于讓React設(shè)置初始狀態(tài),或者綁定方法。還有必須的render方法用于返回JSX的輸出。React組件的所有內(nèi)部邏輯都通過類組件定義中的面向?qū)ο罄^承,從extends React.Component獲得。但是,除了這種用法之外,我并不推薦進(jìn)一步使用類繼承,相反,應(yīng)當(dāng)主要使用類組合(composition)。

注意:利用JavaScript類定義React組件時(shí)還可以使用了另一種語法,通過JavaScript ES6的箭頭函數(shù)來自動(dòng)綁定React組件中的方法:

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      value: '',
    };
  }

  onChange = event => {
    this.setState({ value: event.target.value });
  };

  render() {
    return (
      <div>
        <h1>Hello React ES6 Class Component!</h1>

        <input
          value={this.state.value}
          type='text'
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  }
}

React類組件提供幾個(gè)生命周期方法,用于mount、update和unmount等。比如前面的local storage的例子,可以在生命周期方法中以副作用的方式來執(zhí)行這些操作——即,將輸入框中的最新值保存到local storage中,而在構(gòu)造函數(shù)中可以根據(jù)local storage的值來設(shè)置初始狀態(tài):

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      value: localStorage.getItem('myValueInLocalStorage') || '',
    };
  }

  componentDidUpdate() {
    localStorage.setItem('myValueInLocalStorage', this.state.value);
  }

  onChange = event => {
    this.setState({ value: event.target.value });
  };

  render() {
    return (
      <div>
        <h1>Hello React ES6 Class Component!</h1>

        <input
          value={this.state.value}
          type='text'
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  }
}

利用this.state、this.setState()和生命周期方法,React類組件中的狀態(tài)管理和副作用可以寫在一起。React類組件到現(xiàn)在依然在廣泛使用,盡管后文即將介紹的React函數(shù)組件在現(xiàn)代React應(yīng)用程序中得到了更廣泛的應(yīng)用,因?yàn)楹瘮?shù)組件已經(jīng)不遜于類組件了。

React高階組件

React高階組件(Higher-Order Components,簡稱 HOC)是一種React的高級設(shè)計(jì)模式,是替代Mixin的另一種在組件間復(fù)用邏輯的方法。如果你沒聽說過HOC,可以讀一讀我的另一篇入門文章:高階組件(https://www.robinwieruch.de/gentle-introduction-higher-order-components/)。簡單來說,高階組件就是接收一個(gè)組件作為輸入,然后輸出另一個(gè)組件(并擴(kuò)展其功能)的組件。我們利用前面的例子來看看,怎樣才能將功能提取到可復(fù)用的高階組件中。

const withLocalStorage = localStorageKey => Component =>
  class WithLocalStorage extends React.Component {
    constructor(props) {
      super(props);

      this.state = {
        [localStorageKey]: localStorage.getItem(localStorageKey),
      };
    }

    setLocalStorage = value => {
      localStorage.setItem(localStorageKey, value);
    };

    render() {
      return (
        <Component
          {...this.state}
          {...this.props}
          setLocalStorage={this.setLocalStorage}
        />
      );
    }
  };

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = { value: this.props['myValueInLocalStorage'] || '' };
  }

  componentDidUpdate() {
    this.props.setLocalStorage(this.state.value);
  }

  onChange = event => {
    this.setState({ value: event.target.value });
  };

  render() {
    return (
      <div>
        <h1>
          Hello React ES6 Class Component with Higher-Order Component!
        </h1>

        <input
          value={this.state.value}
          type='text'
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  }
}

const AppWithLocalStorage = withLocalStorage('myValueInLocalStorage')(App);

另一個(gè)高級React設(shè)計(jì)模式就是React Render Prop組件,通常代替React高階組件使用。我不在給出這種抽象的例子,更多內(nèi)容請查看網(wǎng)上的一些教程。

React高階組件和React Render Prop組件在今天都在被廣泛使用,盡管React函數(shù)組件和React鉤子(后文會(huì)介紹)也許對于React組件的抽象更好。不過,高階組件和Render Prop也可以用在函數(shù)組件上。

03

React函數(shù)組件

React函數(shù)組件等價(jià)于React類組件,但它表現(xiàn)為一個(gè)函數(shù),而不是一個(gè)類。過去函數(shù)組件沒有狀態(tài)也無法使用副作用,因此它們被稱為“無狀態(tài)函數(shù)組件”,但自從React鉤子出現(xiàn)后,函數(shù)組件就復(fù)活了。

React鉤子給函數(shù)組件帶來了狀態(tài)和副作用。React不僅帶有各種內(nèi)置的鉤子,還允許創(chuàng)建自定義的鉤子。我們來看看前面的類組件的例子怎樣改寫成函數(shù)組件:

const App = () => {
  const [value, setValue] = React.useState('');

  const onChange = event => setValue(event.target.value);

  return (
    <div>
      <h1>Hello React Function Component!</h1>

      <input value={value} type='text' onChange={onChange} />

      <p>{value}</p>
    </div>
  );
};

這段代碼僅在輸入框上演示了函數(shù)組件。由于要捕獲輸入框的值,就需要使用組件狀態(tài),因此這里用到了內(nèi)置的React.useState鉤子。

React鉤子還可以在函數(shù)組件中實(shí)現(xiàn)副作用。一般來說,內(nèi)置的useEffect鉤子可以用來在任何props或state發(fā)生變化時(shí)執(zhí)行一個(gè)函數(shù):

const App = () => {
  const [value, setValue] = React.useState(
    localStorage.getItem('myValueInLocalStorage') || '',
  );

  React.useEffect(() => {
    localStorage.setItem('myValueInLocalStorage', value);
  }, [value]);

  const onChange = event => setValue(event.target.value);

  return (
    <div>
      <h1>Hello React Function Component!</h1>

      <input value={value} type='text' onChange={onChange} />

      <p>{value}</p>
    </div>
  );
};

這段代碼演示了useEffect鉤子的用法,每次狀態(tài)中的輸入框的值改變時(shí),該鉤子就會(huì)被執(zhí)行。當(dāng)提供給useEffect鉤子的函數(shù)被執(zhí)行時(shí),它會(huì)利用最新的值更新local storage中的值。此外,函數(shù)組件的初始狀態(tài)也可以使用useState鉤子從local storage中讀取。

最后一點(diǎn),我們可以將講個(gè)鉤子提取出來,封裝成一個(gè)自定義鉤子,這樣可以保證組件狀態(tài)永遠(yuǎn)和local storage同步。它在最后會(huì)返回一個(gè)值和setter函數(shù),供函數(shù)組件使用:

const useStateWithLocalStorage = localStorageKey => {
  const [value, setValue] = React.useState(
    localStorage.getItem(localStorageKey) || '',
  );

  React.useEffect(() => {
    localStorage.setItem(localStorageKey, value);
  }, [value]);

  return [value, setValue];
};

const App = () => {
  const [value, setValue] = useStateWithLocalStorage(
    'myValueInLocalStorage',
  );

  const onChange = event => setValue(event.target.value);

  return (
    <div>
      <h1>Hello React Function Component!</h1>

      <input value={value} type='text' onChange={onChange} />

      <p>{value}</p>
    </div>
  );
};

由于這段代碼是從函數(shù)組件中提取出來的,它可以用于任何其他組件,以實(shí)現(xiàn)業(yè)務(wù)邏輯的復(fù)用。它與Mixin、高階組件和Render Prop組件一樣都是高級設(shè)計(jì)模式。但是需要指出的是,React的函數(shù)組件也可以用高階組件和Render Prop組件來增強(qiáng)。

React函數(shù)組件、鉤子和類組件是目前編寫現(xiàn)代React應(yīng)用程序的標(biāo)準(zhǔn)。但是,我堅(jiān)信以后函數(shù)組件和鉤子將取代類組件。屆時(shí),類組件也許只會(huì)出現(xiàn)在舊的應(yīng)用程序和教程中,就像今天的 createClass組件和Mixin一樣。高階組件和Render Prop組件也同理,它們也會(huì)被鉤子取代。

04

寫在最后

所有React的組件在Pros的用法方面的理念都是一樣的,都是將信息沿著組件樹向下傳遞。但是,類組件和函數(shù)組件對于狀態(tài)和副作用的用法是不同的,還有生命周期方法和鉤子。

這篇文章介紹了所有不同種類的React組件及其用法,以及它們在歷史中的位置。最后總結(jié)一下,現(xiàn)在使用類組件、函數(shù)組件和鉤子、高階組件和Render Prop組件等高級概念是完全沒問題的。但是也應(yīng)當(dāng)了解到,舊的React應(yīng)用程序和教程也會(huì)使用一些只有以前才使用的舊組件和設(shè)計(jì)模式。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
javascript – react-flux應(yīng)用程序的可重用性/可伸縮性問題
【react】子組件向父組件傳值
總結(jié) React 組件的三種寫法
React:組件基礎(chǔ)篇
使用react-native中的Navigator組件進(jìn)行頁面導(dǎo)航
React半科普文
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服