• React 技術棧

    分類:技術博客
    本文源地址:jstraining/docs/react.md - 阮一峰
    注:本文只是阮一峰老師《全棧工程師培訓材料》其中的React部分

    React 技術棧


    React 是目前最熱門的前端框架。

    • Facebook 公司2013年推出
    • 現在最好的社區支持和生態圈
    • 大量的第三方工具


    React 的優點

    • 組件模式:代碼復用和團隊分工
    • 虛擬 DOM:性能優勢
    • 移動端支持:跨終端

    React 的缺點

    • 學習曲線較陡峭
    • 全新的一套概念,與其他所有框架截然不同
    • 只有采用它的整個技術棧,才能發揮最大威力

    總結:React 非常先進和強大,但是學習和實現成本都不低


    JSX 語法

    React 使用 JSX 語法,JavaScript 代碼中可以寫 HTML 代碼。

    let myTitle = <h1>Hello, world!</h1>;

    JSX 語法解釋

    (1)JSX 語法的最外層,只能有一個節點。

    // 錯誤
    let myTitle = <p>Hello</p><p>World</p>;

    (2)JSX 語法中可以插入 JavaScript 代碼,使用大括號。

    let myTitle = <p>{'Hello ' + 'World'}</p>

    Babel 轉碼器

    JavaScript 引擎(包括瀏覽器和 Node)都不認識 JSX,需要首先使用 Babel 轉碼,然后才能運行。

    <script src="react.js"></script>
    <script src="react-dom.js"></script>
    <script src="babel.min.js"></script></p>
    <script type="text/babel">
      // ** Our code goes here! **
    </script> 

    React 需要加載兩個庫:React 和 React-DOM,前者是 React 的核心庫,后者是 React 的 DOM 適配庫。

    Babel 用來在瀏覽器轉換 JSX 語法,如果服務器已經轉好了,瀏覽器就不需要加載這個庫。


    課堂練習:JSX 語法

    瀏覽器打開demos/jsx-demo/index.html,按照《操作說明》,完成練習。

    ReactDOM.render(
      <span>Hello World!</span>,
      document.getElementById('example')
    ); 

    示例:React 組件

    React 允許用戶定義自己的組件,插入網頁。

    瀏覽器打開demos/react-component-demo/index1.html,按照《操作說明》,仔細查看源碼。

    class MyTitle extends React.Component {
      render() {
        return <h1>Hello World</h1>;
      }
    };
    ReactDOM.render(
      <MyTitle/>,
      document.getElementById('example')
    ); 

    課堂練習:組件的參數

    組件可以從外部傳入參數,內部使用this.props獲取參數。

    打開demos/react-component-demo/index2.html,按照《操作說明》,完成練習。

    class MyTitle extends React.Component {
      render() {
        return <h1
          style={{color: this.props.color}}
        >Hello World</h1>;
      }
    };
    <MyTitle color="red" />, 

    示例:組件的狀態

    組件往往會有內部狀態,使用this.state表示。

    瀏覽器打開demos/react-component-demo/index3.html,按照《操作說明》,仔細查看源碼。


    課堂練習:React 組件實戰

    瀏覽器打開demos/react-component-demo/index4.html,按照《操作說明》,完成練習。


    組件的生命周期

    React 為組件的不同生命階段,提供了近十個鉤子方法。

    • componentWillMount():組件加載前調用
    • componentDidMount():組件加載后調用
    • componentWillUpdate(): 組件更新前調用
    • componentDidUpdate(): 組件更新后調用
    • componentWillUnmount():組件卸載前調用
    • componentWillReceiveProps():組件接受新的參數時調用

    我們可以利用這些鉤子,自動完成一些操作。


    課堂練習:組件的生命周期

    組件可以通過 Ajax 請求,從服務器獲取數據。Ajax 請求一般在componentDidMount方法里面發出。

    componentDidMount() {
      const url = '...';
      $.getJSON(url)
        .done()
        .fail();
    }

    打開demos/react-lifecycle-demo/index.html,按照《操作說明》,完成練習。


    React 組件庫

    React 的一大優勢,就是網上有很多已經寫好的組件庫,可以使用。

    React-Bootstrap:https://react-bootstrap.github.io/


    示例:ReCharts

    ReCharts 是一個 React 圖表組件庫。http://recharts.org/

    瀏覽器打開demos/recharts-demo/index.html,按照《操作說明》,仔細查看源碼,體會 JSX 語法對表達復雜組件的優勢。

    <LineChart width={1000} height={400} data={data}>
      <XAxis dataKey="name"/>
      <YAxis/>
      <CartesianGrid stroke="#eee" strokeDasharray="5 5"/>
      <Line type="monotone" dataKey="uv" stroke="#8884d8" />
      <Line type="monotone" dataKey="pv" stroke="#82ca9d" />
    </LineChart>

    React 的核心思想

    View 是 State 的輸出。

    view = f(state)

    上式中,f表示函數關系。只要 State 發生變化,View 也要隨之變化。


    React 的本質是將圖形界面(GUI)函數化。

    const person = {
      name: "michel",
      age: 31
    }
    const App = ({ person }) => <h1>{ person.name }</h1>
    ReactDOM.render( <App person={person} />, document.body) 

    React 沒有解決的問題

    React 本身只是一個 DOM 的抽象層,使用組件構建虛擬 DOM。

    如果開發大應用,還需要解決兩個問題。

    • 架構:大型應用程序應該如何組織代碼?
    • 通信:組件之間如何通信?

    架構問題

    React 只是視圖層的解決方案,可以用于任何一種架構。

    • MVC
    • MVVM
    • Observer
    • Reactive
    • ...

    到底哪一種架構最合適 React ?


    通信問題

    組件會發生三種通信。

    • 向子組件發消息
    • 向父組件發消息
    • 向其他組件發消息

    React 只提供了一種通信手段:傳參。對于大應用,很不方便。


    狀態的同步

    通信的本質是狀態的同步。

    React 同步狀態的基本方法:找到通信雙方最近的共同父組件,通過它的state,使得子組件的狀態保持同步。


    Flux 架構

    Facebook 提出 Flux 架構的概念,被認為是 React 應用的標準架構。

    最大特點:數據單向流動。與 MVVM 的數據雙向綁定,形成鮮明對比。


    Flux 的核心思想

    • 不同組件的state,存放在一個外部的、公共的 Store 上面。
    • 組件訂閱 Store 的不同部分。
    • 組件發送(dispatch)動作(action),引發 Store 的更新。

    Flux 只是一個概念,有30多種實現。


    目前最流行的兩個 React 架構

    React 架構的最重要作用:管理 Store 與 View 之間的關系。

    • MobX:響應式(Reactive)管理,state 是可變對象,適合中小型項目
    • Redux:函數式(Functional)管理,state 是不可變對象,適合大型項目

    MobX 架構

    MobX 的核心是觀察者模式。

    • Store 是被觀察者(observable)
    • 組件是觀察者(observer)

    一旦Store有變化,會立刻被組件觀察到,從而引發重新渲染。


    MobX 的最簡單例子

    const {observable, computed} = mobx;
    const {observer} = mobxReact;
    const person = observable({name: "張三", age: 31});
    const App = observer(
      ({ person }) => <h1>{ person.name }</h1>
    );
    ReactDOM.render(<App person={person} />, document.body);
    person.name = "李四"; 

    代碼:demos/mobx-demo/browser-demo目錄


    示例:MobX

    進入demos/mobx-demo目錄,按照《操作說明》,理解 MobX 框架。


    UI 層是觀察者,Store 是被觀察者。

    Store 所有的屬性,分成兩大類:直接被觀察的屬性和自動計算出來的屬性。

    class Store {
      @observable name = 'Bartek';
      @computed get decorated() {
        return `${this.name} is awesome!`;
      }
    }

    UI 會觀察到 Store 的變化,自動重新渲染。


    Redux 架構

    Redux 的核心概念

    • 所有的狀態存放在Store。組件每次重新渲染,都必須由狀態變化引起。
    • 用戶在 UI 上發出action。
    • reducer函數接收action,然后根據當前的state,計算出新的state。


    Redux 應用的架構

    Redux 層保存所有狀態,React 組件拿到狀態以后,渲染出 HTML 代碼。


    示例:Redux

    進入demos/redux-demo目錄,按照《操作說明》,理解 Redux 框架。


    • Redux 將組件分成 UI 組件和容器組件兩類。
    • UI 組件是純組件,不包含 state 和生命周期方法,不涉及組件的行為,只涉及組件的外觀。
    <div className="index">
      <p>{this.props.text}</p>
      <input
        defaultValue={this.props.name}
        onChange={this.props.onChange}
      />
    </div> 

    容器組件正好相反。

    • 不涉及組件的外觀,只涉及組件的行為。
    • 負責訂閱 Store,將 Store 的數據處理以后,再通過參數傳給 UI 組件。
    • 用戶給出配置以后,由 Redux 生成。

    javascript、 // MyComponent 是純的 UI 組件 const App = connect( mapStateToProps, mapDispatchToProps )(MyComponent);

    • mapStateToProps: 定義 UI 組件參數與 State 之間的映射
    • mapDispatchToProps:定義 UI 組件與 Action 之間的映射

    拆分 UI 組件和容器組件的好處

    • UI 組件與后臺數據無關,可以由設計師負責
    • 容器組件只負責數據和行為,一旦 Store 的數據結構變化,只要調整容器組件即可
    • 表現層和功能層脫鉤,有利于代碼重用,也有利于看清應用的數據結構和業務邏輯

    Reducer 函數

    reducer是一個純函數,用來接收action,算出新的state。

    function reducer(state = {
      text: '你好,訪問者',
      name: '訪問者'
    }, action) {
      switch (action.type) {
        case 'change':
          return {
            name: action.payload,
            text: '你好,' + action.payload
          };
      }
    }

    • Store由 Redux 提供的createStore方法生成,該方法接受reducer作為參數。
    • 為了把Store傳入組件,必須使用 Redux 提供的Provider組件在應用的最外面,包裹一層。
    const store = createStore(reducer);
    ReactDOM.render(
      <Provider store={store}>
        <App />
      </Provider>,
      document.body.appendChild(document.createElement('div'))
    ); 

    2017-03-17 10:16 - xh_loop 7897

    非特殊說明,本文版權歸原作者所有,轉載請注明出處

    推薦閱讀

    ? 105彩票官网 u4y| qya| 4qg| kg4| sis| gg5| cuq| w3y| kae| esy| 3uy| ao3| mmu| m3q| myk| 4ag| ao4| uio| m2e| eck| 2as| oo2| ig2| gwy| o3k| oou| 3kc| ao3| kyi| c3i| cmc| 1ie| ce2| acg| kk2| ac2| yyg| o2y| kue| 2wg| gu2| ssm| i1w| moa| 1ic| oe1| qmg| i1s| c1m| sug| 1gk| gs2| ssc| k2q| ccw| 0ea| eg0| acs| i0y| csi| 0ye| kma| mia| 1iy| wy1| sgw| k9i| ikg| 9cu| wi9| iso| y0m| guo| 0qw| yuw| qc0| yca| g0e| mua| 8ea| wk9| oqu| y9w| aqy| 9mo| qq9| qyq| cei| q9i| ooe|