手把手教你用 React Hooks 開發移動端網站,從入門到實踐

React 已經是 JavaScript 生態系統中最受歡迎的前端框架之一。儘管人們已經對它讚不絕口,但 React 團隊仍然在努力讓它變得更好。

在 2018 ReactConf 大會上,React 官方發佈了 Hooks,隨後它席捲了整個 React 開發界。

React Hooks 是 React 庫的新增功能,它允許你編寫狀態邏輯並使用其他 React 功能,同時無需編寫類組件。你甚至可以單獨使用 Hooks 來製作自己的應用程序,這對 React 相關的從業者來說是一次重大變革。

手把手教你用 React Hooks 開發移動端網站,從入門到實踐

今天給大家帶來一門 React Hooks 的課程《React Hooks 從入門到實踐》,課程將對 React Hooks 做全方位的分析,並通過純 Hooks 函數組件對 CNode 網站進行移動端頁面的開發,實戰過程中還會介紹前端開發中常用技術棧的使用。

課程實戰用到的技術棧 React + React-Router+ Antd-Mobile + Axios ,實戰部分使用最新 vw 方式做移動端的適配,拋棄 rem 的形式擁抱變化。重寫 Axios 請求庫,做到請求返回統一處理。開發環境的搭建可以作為一個種子項目,方便在工作中啟動新項目時直接使用。

項目效果圖:

手把手教你用 React Hooks 開發移動端網站,從入門到實踐

教程開始:

React 作為 Facebook 推出的前端主流框架之一,在版本升級上一直是採用平滑升級的模式。在升新版本的時候,無論是增加或者刪除了某些 API,React 都能做到版本向後兼容,也就是用舊版本的寫法,最新的 React 包也能做到基本支持。這次也不例外,在 v16.8 版本引入了全新的 API,名叫 React Hooks。引用官方的解釋就是三個點

  • 完全可選的。你無需重寫任何已有代碼就可以在一些組件中嘗試 Hooks。但是如果你不想,你不必現在就去學習或使用 Hooks。
  • 100% 向後兼容的。Hooks 不包含任何破壞性改動。
  • 現在可用。Hooks 已發佈於 v16.8.0。

React 官方沒有計劃從 React 中移除 Class,但是我相信不久的將來,Hooks 將被大範圍使用。相比之下 Hooks 可以涵蓋所有 Class 組件的應用場景,且提供了更高的靈活性、可測試性和代碼的複用能力。Hooks 不會影響你對 React 概念的理解。恰恰相反,Hooks 為已知的 React 概念提供了更直接的 API:props, state,context,refs 以及生命週期。在後面的章節裡,筆者還會一一介紹上面列出的 API。

Dan Abramov 在社交他的社交網站上也毫不吝嗇的給出了他的想法。

手把手教你用 React Hooks 開發移動端網站,從入門到實踐

Hooks 將會是 React 的未來。

我們為什麼不再需要 Class 組件

存在即是合理的,React Hooks 要解決的問題是狀態共享,是繼 render-props 和 higher-order components 之後的第三種狀態共享方案,不會產生 JSX 嵌套地獄問題。這個狀態指的是狀態邏輯,所以稱為 狀態邏輯複用會更恰當,因為只共享數據處理邏輯,不會共享數據本身。

在 React Hooks 推出之前,React 便已經有函數組件了,那麼已經有了函數組件,為什麼開始還要引入 Class 組件呢?

早些時候的 React 組件以有無狀態(state)分為兩種,代碼如下。

<code>// 有狀態組件
class Hello extends React.Component {
constructor(props) {
super(props)
this.state = {
text: 'Hello World'
}

render() {
return
{text}

}
}
}

// 無狀態組件
// 狀態通過父組件傳入
const Hello = (props) =>
{props.text}
/<code>

我們可以通過 Class 組件的 this 上下文去保存和訪問狀態(state),但是函數組件在其作用域內很難維持住這個狀態,試想如果再次運行函數的話,所有的狀態都將被重置。所以我們才一直使用 Class 的形式編寫有狀態組件。

Hooks 編寫函數組件,它的狀態是如何維持的呢

瞭解過 React Fiber 的同學應該知道,類組件中的狀態其實保存在 Fiber 的屬性 memoizedState 上,並不是在 Class 的 this.state 上。那麼回過頭來看 React Hooks 組件的狀態,其實也是去訪問 Fiber 上的 memoizedState 屬性,這樣看來,問題就迎刃而解了。

兩種寫法的對比分析

繁重的寫法。

下面是一段簡單的以 Class 形式書寫的組件代碼。

<code>import React, { Component } from "react";

export default class MyButton extends Component {
constructor() {
super();
this.state = {
text: "點擊"
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
text: "改變"
});
}
render() {
const { text } = this.state;
return <button>{text}/<button>;
}
}/<code>

僅僅是需要一個按鈕組件,代碼量已經接近 20 行之多,可能你會覺得 20 行並不多,但是當組件內部需要控制一些狀態的時候,那代碼量就不僅僅是 20 行這麼簡單了。包括整個 React 項目都是由各個組件拼裝而成,層層嵌套,再加上狀態管理插件如 Redux、Mobx 等,就會是一場 “災難”。

反觀 Hooks 的寫法:

<code>import React from "react";

export default const MyButton = () => {
const [text, setText] = useState('點擊')
return <button>{text}/<button>
}/<code>

在 Hooks 出現之前,React 也是可以用函數寫組件的,但是隻能寫一些無狀態的純組件 (Pure Component) ,也就是內部是不能有屬於自己的狀態變量。上述代碼中 Hooks 實現了函數組件管理自身狀態的方式,不僅在代碼量上得以控制,書寫上也簡便了不少。受限於現代瀏覽器,所有最新 ES6 + 的寫法,不是所有瀏覽器都會支持。類組件的寫法在經過 babel 編譯後會編譯成 ES5 寫法,才能讓各大瀏覽器得以支持和運行。這就導致了編譯後類組件比函數組件多一層繼承 React.Component 的代碼,從這個角度出發,Hooks 寫法降低了編譯後的代碼了減少 bundle 包的大小。

複雜組件變得難以理解。

隨著組件代碼的增多,狀態與狀態緊密相連,想把組件拆分的細緻那就變得難上加難。重複的邏輯在不同的組件和生命週期函數之間不斷出現,到那時項目就變得不可維護。

開發環境的搭建

課程總共為 10 章,1 ~ 8 章以實例和原理講解為主,9 ~ 10 章 為實戰章節。

所以 1 ~ 8 章筆者只需要通過官方提供的項目初始化工具 create-react-app 來完成課程內部代碼的講解。

首先電腦裡必須事先安裝 Node 環境。。

檢測當前 Node 版本和 NPM 版本,執行命令行。

<code>node -v
npm -v/<code>

如果已經安裝過的同學會打印出相應的 Node 版本,當然實驗樓也提供了前端的開發環境,內置 Node 和 NPM,已經在全局安裝了 cnpm 包,沒有科學上網的同學儘量使用 cnpm 安裝 node_modules 包,因為有些包是放在國外的服務器,直接使用 npm 可能會安裝不上或者需要很久的時間,對大家的開發體驗也是不好的。

全局安裝 create-react-app。

<code>cnpm install create-react-app -g/<code>

安裝完畢之後,通過指令可以生成項目。

<code>// my-app 為項目文件夾的名字,可自定義 

npx create-react-app my-app
or
npm init react-app myapp/<code>

初始化項目結束之後,進入進入文件夾,通過 npm run start 啟動項目,默認的端口會是 3000,而實驗樓在線開發環境只對外開放 8080 端口,所以我們要對文件裡的腳本做一些改動。

有兩種方式改變 create-react-app 初始化項目的開發環境啟動端口。

  • 修改 package.json 的>
<code>"scripts": {
"start": "PORT=8080 react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},/<code>

要注意的是,如果是 Windows 用戶建議在 PORT 前加上一個 cross-env,需要通過 cnpm install cross-env -D 下載到開發依賴 devDependencies 中。

cross-env 是一個運行跨平臺設置和使用環境變量的腳本 .cross-env 使得您可以使用單個命令,而不必擔心為平臺正確設置或使用環境變量。

  • 通過修改 node_modules/react-scripts/scripts/start.js 腳本第 60 行的端口號,如下。
<code>// line 60
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 8080;/<code>

端口修改完之後,點開右邊的 “Web 服務”,會在瀏覽器打開一個在線頁面,如下圖所示。

手把手教你用 React Hooks 開發移動端網站,從入門到實踐


打開瀏覽器,你會遇到如下報錯。

手把手教你用 React Hooks 開發移動端網站,從入門到實踐


原因是實驗樓環境啟動的在線網址是 https 協議,而項目熱更新用的是 ws 協議,所以我們需要將 ws 協議改成 wss 協議。打開項目 node_modules 目錄,找到 node_modules/react-dev-utils/webpackHotDevClient.js 腳本,將第 60 行修改為 wss 如下圖。

手把手教你用 React Hooks 開發移動端網站,從入門到實踐


重新通過 npm run start 啟動項目,再次點開 “Web 服務”,如下圖所示,便是實驗環境配置成功。

手把手教你用 React Hooks 開發移動端網站,從入門到實踐


項目運行的時候有強迫症的同學可以關閉 eslint ,具體方法首先運行指令:

<code>npm run eject/<code>

根目錄會多出一個 config 文件夾,進入文件夾打開腳本 webpack.config.js,把 eslint 的配置關閉,如下圖所示


手把手教你用 React Hooks 開發移動端網站,從入門到實踐


將紅框的內容註釋之後,重啟項目,命令行就會不顯示 eslint 語法報錯。

篇幅有限,今天就介紹到這裡,對 前端 和 React Hooks 感興趣的同學,歡迎來實驗樓邊敲代碼邊學習~


分享到:


相關文章: