1. 程式人生 > >React學習心得淺談

React學習心得淺談

文章目錄

React學習淺談(1)-技術棧

這兩天花了點時間學習了下React,本人並不是一名純前端研發人員,之所以想學習React只是想補全自己的技術棧。之前一直都是使用jquery+bootstrap來開發頁面,其實大多數情況下這種技術棧也夠了。但是現在都流行前後端分離,所以諸如React和Vue這類MVVM前端框架才會大行其道。

這所以寫這篇文章,主要還是為了對自己這兩天的學習做個總結,免得後面遺忘。同時,也希望能給那些想學習React卻比較迷茫的同行們來個拋磚引玉,說下我個人的學習路線。

我覺得React的優點在於元件化以及JSX語法。元件化實現了頁面通用元素的封裝,提高頁面元素的複用性;而JSX語法則便於我們在js中編寫html程式碼。

1. React技術棧

學習React是有一定的學習成本的,主要是如果想要用它進行專案開發,就需要學習一系列它的技術棧,包括基本知識、執行編譯環境和一系列外掛。而我也只是學了個冰山一角。

1.1. 執行編譯環境

我採用的nodejs+npm+yarn+webpack。

  • Nodes:javascript執行環境,我們編寫的程式碼需要在nodejs上執行。

  • npm:在安裝完nodejs後,預設就已經按轉了npm了。npm是包管理軟體,能夠快速地基於命令列的方式安裝各種組建包,並對組建包進行管理。例如:

    npm install -g create-react-app --save-dev
    
  • Yarn:yarn和npm功能類似,都是對包進行管理。yarn具有快取包的功能,下載過一次,下次安裝可以直接從本地進行安裝。

    yarn add react-redux
    
  • Webpack:打包工具,用於將javascript進行打包。

1.2. ES6

要學習並使用react,ES6是必須要學習的。在react開發過程中,會大量地使用到ES6中的各種特性。諸如:

  • class類:例如class InputComponent extends React.Component
  • let/const:定義變數、函式會大量使用到let和const,而不會再去使用var;
  • import/export:需要使用import引入元件,並將自己寫的元件通過export輸出,方便其他元件引用;
  • 模板字串:便於編寫字串,不需要通過+來組裝字串。
  • Object.assign():用於將兩個物件進行合併。

還有其他很多特性會用到,所以對ES6的學習非常重要。

1.3. React

React是基於元件化的思想進行開發的js框架,所以我們需要有元件化的思想。學習React主要會用到:

  • jsx語法:通過該語法方便在js中編寫html程式碼;只能有一個頂級元素!
  • React.Component:這是React元件的基類,所以編寫的React元件都要繼承這個類。元件之間的引數的傳遞採用this.props進行傳遞。
  • ReactDOM:用於將元件渲染到頁面上。

1.4 Redux

Redux用於對JavaScript的狀態進行管理,通過Redux,可以有效銜接頁面操作和操作完成後的狀態之間的關係,以及基於雙向繫結實現狀態對監聽狀態變化的監聽器的影響。所有的狀態資料儲存在同一個Store中。

其中一個詞:狀態,很重要。我們在使用Redux,在動作產生後(例如頁面的一個點選事件),那麼傳遞給狀態的不是對事件的處理動作,而是事件完成後的狀態。例如點選登陸按鈕進行登入,狀態不是執行動作的事件,而是動作完成後的狀態:使用者名稱密碼是什麼?驗證是否通過?

所以Redux會涉及到四個概念:

  • Action:該動作不是點選事件的動作,而是點選之前或者點選之後設定狀態的動作。例如:

    const loginReceived = (checked)=>{
        type:'login_received',
        checked
    }
    

    從上面可以看出,我們傳遞的不是事件,而是是否驗證通過這個狀態。

  • Reduce:用於接受action產生的狀態,並對store中的狀態進行修改。所以reduce會在建立store時作為引數傳進去,一旦有action被dispatch到store中,store就會呼叫reduce進行處理。Reduce是一個純函式。並且只能有一個。多個Reduce通過combineReducers進行組合。

  • Dispatch:動作分發,將動作分發到store中。

  • Store:用於儲存狀態State。

1.5 Middleware

那麼既然用於傳遞的是使用者名稱、密碼、是否通過,那麼“驗證”事件什麼時候執行呢?理論上應該是在狀態——獲取到是否通過——之前:動作—>驗證—>狀態。

也就是說“驗證”這一步是發生在Action發生之後,Reduce之前。這裡就涉及到middleware元件。middleware是一個概念,類似於攔截器,用於攔截每一個dispatch到store中的action,在action發生之前和發生之後進行攔截處理。

例如記錄日誌,可以使用createLogs,上面說的中間處理,可以使用redux-thunk

2. 環境搭建

環境搭建包括開發環境和編譯環境。

2.1 搭建開發環境

我主要是用VS Code進行開發,優點不多說,絕對好用就是了。需要安裝一些外掛才能發揮更強大的作用。我裝的外掛如下圖所示:

在這裡插入圖片描述

2.2 搭建編譯環境

  • 安裝nodejs。這個可以直接下載安裝包進行安裝,安裝完成後,也就支援npm了。

  • 安裝yarn。windows平臺下下載安裝包安裝,mac可以使用homebrew進行安裝。

    brew install yarn
    
  • 切換淘寶映象:

    npm config set registry https://registry.npm.taobao.org
    
  • 安裝cnpm

    npm install -g cnpm 
    
  • 安裝react開發環境建立元件。

    npm install -g create-react-app
    

    以後可以直接使用create-react-app projectname 來建立開發環境,會預設初始化好開發環境需要的基本依賴。

2.3 搭建完整的專案開發環境

接下來介紹如何搭建一個完整的專案開發環境。例如專案名稱是一個天氣查詢專案,展示當前的天氣。那麼我們可以在命令列下做如下操作:

cd Documents/projects/
create-react-app weather

等待專案初始化環境建立完成後,可以通過yarn安裝其他以來包:

yarn add redux
yarn add react-redux
yarn add redux-logger
yarn add redux-thunk
yarn add cross-fetch

如果需要其他依賴包,也可以這樣安裝即可。

3. 編碼設計

我們就以編寫一個獲取天氣的簡單小專案來上手。

3.1 建立專案目錄

預設我們在src目錄下建立四個子目錄:

  • actions:用於存放action的js檔案。再次記住:action不是事件函式,是傳遞狀態state的修改值的函式。
  • reduces:用於存放reduce的js檔案。
  • containers:用於存放將state、dispatch方法與有狀態元件(也就是用於最後渲染介面的元件)進行連線的函式。
  • components:用於存放無狀態元件和有狀態元件的函式。
    • 無狀態元件:純元件,不關心state,只根據傳遞的props編寫html元素的元件。例如一個input或者button元件,而元件中的動作也會通過引數觸發有狀態元件中的函式,從而實現對狀態的修改。
    • 有狀態元件:需要關心和設定state,可能會包含多個無狀態元件。最終會通過 ReactDOM.render 渲染成頁面的元件。

可能我們還會建立utils目錄或者其他目錄。最後,還有一個最外層的index.js檔案,我們一般在這裡建立store,並渲染頁面。

3.2 編寫action

編寫action,我們需要分析頁面獲取天氣會產生幾個事件。頁面的功能是:“根據選擇的不同地市,獲取該地市的天氣,將獲取到的地市展示在介面上“。根據這句話,我們來分析有哪些action。

  • 選擇不同的地市:”選擇“是事件,也就是onChange或者onClick事件。選擇的“地市”就是狀態值。所以我們會建一個selectedCity(cityCode)的函式。注意方法名是selected,而不是select,用的是過去式,表示被選擇的,是一種狀態——天氣“待獲取”。
  • 獲取該地市的天氣:從字面上看,應該是發起ajax請求獲取天氣。但是預設的action是不能傳送ajax請求的,只傳遞狀態。這裡傳遞什麼狀態?那就是天氣“獲取中”,所以我們會建一個requestWeather(cityCode)的函式。那ajax在哪兒發起呢?會用到前面說的redux-thunk來發起。
  • 將獲取到的天氣展示在介面上:自然而然,我們會看到,這裡的狀態是“已獲取”到天氣,那麼我們傳遞的窗臺值就是獲取到的天氣資訊,可以是json。所以我們會建立一個receivedWeather(cityCode,json)的函式。
  • 最後就是ajax請求函式。該函式通過redux-thunk來編寫,同時會呼叫requestWeather(cityCode)receivedWeather(cityCode,json)函式,來完成獲取天氣之前的準備動作(例如彈出轉圈等待)和獲取到天氣之後的動作(例如渲染到頁面)。所以我們會建立一個fetchWeather(cityCode)函式。

3.3 編寫reduces

因為reduce是用於修改state的,並且是一個純函式。那麼首先第一步,也是最重要的就是想想看我們的state長什麼樣子?也就是什麼樣的資料結構(json結構)。

{
    selectedCity:'xxx', //選擇的地市
    weatherInfo:{//天氣資訊,是一個json
        
    },
    isFetching:true/false //是否獲取中,如果是ajax請求中,則是true,否則是false。
}

想好了state長什麼樣子,就要考慮編寫幾個reduce函式呢?我這裡有個個人看法,就是看state裡有幾個頂級的key,就寫幾個函式。例如上面有selectedCityweatherInfoisFetching三個頂級key,那麼我們就建立三個同名的函式。為什麼要這樣呢?一是為了方法的獨立性,便於方法重用;二是正好基於combineReduces函式,在整合這三個reduce函式後,就會生成如上的資料結構。

既然是寫三個函式,同時也說了這樣可以保證方法的獨立性。那麼每個函式返回的state也需要相應的只返回對應的獨立的結果。例如selectedCity函式返回的state就只是一個字串。是不是很獨立呢?

3.4 編寫components

編寫components,就需要考慮:

  • 頁面長什麼樣子,哪些頁面元素是無狀態元件,哪些是有狀態元件;
    • select 元件是無狀態元件
    • weatherApp 是有狀態元件,裡面包含select元件。
  • 在編寫元件的時候,需要考慮state裡有什麼元素,哪些元素是元件需要用到的;
    • select 元件會用到 selectedCity 的值;
    • weatherApp 會用到 weatherInfo 的值;同時還會根據 isFetching 的值顯示“載入中…“。
  • 還要考慮元件觸發的事件( `onClick``)會呼叫哪個action。
    • select 元件的onChange事件會觸發 selectedCity 函式;
    • weatherAppcomponentWillReceiveProps() 方法會觸發 fetchWeather 函式,用於監聽一旦selectedCity 的值發生變化,就獲取天氣。

3.5 編寫containers

containers的寫法一般是固定的,就三個作用:

  • 將state的值傳遞給元件的props,我們會建立mapStateToProps(state)方法;(當然也可以不寫這個函式,那就是將state作為props的一部分傳遞給元件)
  • 將dispatch各個action的函式傳遞給元件的props,方便業務呼叫(當然也可以直接傳dispatch作為props的一部分),我們會建立 mapDispatchToProps(dispatch)方法;
  • 呼叫 connect 方法,將元件與redux連線起來,並將上面的兩個方法作為connect的引數。

經過上面的分析,我們就可以編寫程式碼了,分別在對應的目錄下建立js檔案,並在js檔案中建立對應的方法。