乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      一文詳解 React 組件類型

       黃爸爸好 2019-03-25

      腳本之家

      你與百萬開發(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è)計模式今天依然在使用,它們已成了構(gòu)建React應(yīng)用程序的標(biāo)準(zhǔn),而另一些類型的組件只會在舊的應(yīng)用和新手教學(xué)中出現(xiàn)。

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

      01

      React createClass組件

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

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

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

      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>
          );
        },
      });

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

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

      React Mixin

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

      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>
          );
        },
      });

      在這個例子中,Mixin提供了組件的初始狀態(tài),而該初始狀態(tài)是從local storage中讀取的,并且還利用setLocalStorage()擴(kuò)展原來的組件,該函數(shù)之后會在組件中被調(diào)用。為了讓Mixin更靈活,我們可以使用一個返回函數(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了,因為它們會帶來一些負(fù)面作用。關(guān)于Mixin的細(xì)節(jié)和消亡過程可以閱讀這里(https:///blog/2016/07/13/mixins-considered-harmful.html)

      02

      React類組件

      React類組件是在JavaScript ES6時引入的,因為直到ES6才支持JS類。有時候它們也被稱為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òu)造器的方法,主要用于讓React設(shè)置初始狀態(tài),或者綁定方法。還有必須的render方法用于返回JSX的輸出。React組件的所有內(nèi)部邏輯都通過類組件定義中的面向?qū)ο罄^承,從extends React.Component獲得。但是,除了這種用法之外,我并不推薦進(jìn)一步使用類繼承,相反,應(yīng)當(dāng)主要使用類組合(composition)。

      注意:利用JavaScript類定義React組件時還可以使用了另一種語法,通過JavaScript ES6的箭頭函數(shù)來自動綁定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類組件提供幾個生命周期方法,用于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)用,因為函數(shù)組件已經(jīng)不遜于類組件了。

      React高階組件

      React高階組件(Higher-Order Components,簡稱 HOC)是一種React的高級設(shè)計模式,是替代Mixin的另一種在組件間復(fù)用邏輯的方法。如果你沒聽說過HOC,可以讀一讀我的另一篇入門文章:高階組件(https://www./gentle-introduction-higher-order-components/)。簡單來說,高階組件就是接收一個組件作為輸入,然后輸出另一個組件(并擴(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);

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

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

      03

      React函數(shù)組件

      React函數(shù)組件等價于React類組件,但它表現(xiàn)為一個函數(shù),而不是一個類。過去函數(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ù)組件中實現(xiàn)副作用。一般來說,內(nèi)置的useEffect鉤子可以用來在任何props或state發(fā)生變化時執(zhí)行一個函數(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)中的輸入框的值改變時,該鉤子就會被執(zhí)行。當(dāng)提供給useEffect鉤子的函數(shù)被執(zhí)行時,它會利用最新的值更新local storage中的值。此外,函數(shù)組件的初始狀態(tài)也可以使用useState鉤子從local storage中讀取。

      最后一點,我們可以將講個鉤子提取出來,封裝成一個自定義鉤子,這樣可以保證組件狀態(tài)永遠(yuǎn)和local storage同步。它在最后會返回一個值和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ù)組件中提取出來的,它可以用于任何其他組件,以實現(xiàn)業(yè)務(wù)邏輯的復(fù)用。它與Mixin、高階組件和Render Prop組件一樣都是高級設(shè)計模式。但是需要指出的是,React的函數(shù)組件也可以用高階組件和Render Prop組件來增強(qiáng)。

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

      04

      寫在最后

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

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

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多