談談React.js的核心入門知識

發表於2015-09-02

近來React.js變得越來越流行,本文就來談一談React.js的入門實踐,通過分析一些常用的概念,以及提供一些入門 的最佳程式設計程式設計方式,僅供參考。

首先需要搞懂的是,React並不是一個框架,React提供了一些新穎的概念、庫 和程式設計原則讓你能夠同時在服務端和客戶端編寫快速、緊湊、漂亮的程式碼來構建 你的web應用。

如果你使用React,那麼可能會涉及到一些常用的概念或技術,包括:

  • ES6 React
  • 虛擬DOM(virtual DOM)
  • 元件驅動開發(component-driven development)
  • 不變性(immutability)
  • 自上而下的渲染(top-down rendering)
  • 渲染路徑和優化
  • 打包工具, ES6, 構建請求, debugging, 路由等
  • 同構React(isomorphic React)

什麼是React.js

React.js不是一個框架

在整個Web應用的MVC架構中,你可以將React看作為檢視層,並且是一個高效 的檢視。React提供了和以往不一樣的方式來看待檢視,它以元件開發為基礎。 對React應用而言,你需要分割你的頁面,使其成為一個個的元件。也就是說,你的 應用是由這些元件組合而成的。

你可以通過分割元件的方式去開發複雜的頁面或某個功能區塊,並且元件是可以 被複用的。這個過程大概類似於用樂高積木去瓶裝不同的物體。我們稱這種程式設計方式稱為 元件驅動開發

React的一大特點是其所擁有的虛擬DOM,它讓頁面渲染變得非常的高效,並且比直接 操縱DOM變得更為可控。這兩大特點的組合使得React具有強大的自上而下的頁面渲染 能力。

好了,React的有兩個特點:元件化和高效的虛擬DOM,但是為什麼它這麼被看好呢? 因為React更多的是一種概念層面的東西,而庫是其次的。也有很多其他遵從了這些思想的第三方實現。和每一個程式設計概念一樣,React尤其 獨有的解決方案、工具和工具。但這裡並不會深入的去討論他們,而是關注React本身。

Virtual DOM

為了跟蹤模型層的變化,並且將其應用到DOM中(也就是渲染),我們需要注意兩個 重要的事情:

  1. 資料是什麼時候改變的
  2. 哪一個(些)DOM元素需要被更新

對於(1)而言,React提供了一個觀察者模型用於替代傳統的髒檢查(dirty checking), 也就是持續的檢查模型的變化。這也就是解釋了為什麼React不需要計算哪些發生 了改變的原因,因為它會立即知道。這個過程減少了計算量,並它應用程式變得 更平滑。但這裡真正有趣的是,React是如何管理DOM操縱的

對於DOM改變(2)而言,React在記憶體中構建了DOM的樹形表示,並且計算出哪個 DOM元素應該被改變。對瀏覽器而言,DOM操縱是比較耗費效能的,因此我們更傾向於 讓其變得最小化。幸運的是,React檢視儘可能少的觸及到DOM元素。給予物件表示而言, 更少的DOM操縱意味著計算會更快,因此DOM改變也被儘可能的減少。

React在底層實現了一個diffing演算法,該演算法使用DOM的樹形表示法,當某個 節點發生變化(標記為dirty)時它會重新計算整個子樹,你會注意到你的模型發生 了改變,因為整個子樹在之後會被重新渲染。關於該演算法的詳細分析可以參考這篇 文章

如何在服務端渲染

因為React在DOM表示時使用了一個虛擬(假的)DOM,因此藉助於這種方式使得在服務端 渲染輸出HTML稱為可能(不借助於JSDom, PhantomJS等)。React還能智慧的識別出 服務端渲染出來的頁面標記,並在客戶端只為這些標記新增事件處理器,這對構建 同構web app非常有用。

有意思的是,React渲染出來的HTML標記都包含了data-reactid屬性,這有助於 React中追蹤DOM節點。

一些閱讀資料

  1. React’s diff algorithm
  2. The Secrets of React’s virtual DOM
  3. Why is React’s concept of virtual DOM said to be more performant than dirty model checking?
  4. virtual-dom

元件驅動開發

對於component-driven development而言,你在一個模板中是看不到整個網站的。 雖然在一開始你可能會遇到一些困難,但是如果進一步的使用這種思路,你會發現 它易於理解,易於維護,並且容易測試。

如何使用React的方式來思考元件開發

下面我們來看如何實現元件驅動開發這一理念。我們看一個例子,這個例子來源於 thinking in react 這篇文章。對於構建一個可過濾的產品列表而言,通常其包括如下的元件結構:

一個元件應該包含什麼

首先,理想的,我們應該遵守單一責任原則 來設計你的元件。當你發下你的元件應該做的更多的時候,你可以考慮將其分割為 更小的元件集合。

因為我們在討論元件層級,因此在你的元件中也會使用到其他元件。我們首先看下 在ES5中元件程式碼是什麼樣子的:

如果使用ES6,你的元件程式碼可以這樣寫:

 JS和JSX

正如你說看到的,我們的元件是JS和HTML程式碼的混合,你可能會覺得這很糟糕,因為 MVC一直在教我們儘可能的隔離檢視和控制邏輯。但另一方,這種混合獲得另一個層面的 單一責任,他使得元件更加的靈活和可重用。

當然,在React中你也可以使用純JS來編寫你的元件:

是的,你會發現這很麻煩,沒有使用HTML來得直觀。因此React提供了JSX (JavaScript eXtension)語法讓你能夠在JS中書寫HTML程式碼。

 什麼是JSX

JSX在ECMAScript的基礎上提供了類似於XML的擴充套件。 JSX和HTML有點像,但也有不一樣的地方。例如,HTML中的class屬性在JSX中 為className。其他不一樣的地方,你可以參考FB的HTML Tags vs. React Components 這篇文章。

但是由於瀏覽器原生並不支援JSX,因此我們需要將其編譯為JS,有很多方法能夠 完成這個任務,後面我們會提到這些方法。此外,Babel也能夠講JSX編譯為JS。

一些參考資料:

  1. JSX in depth
  2. Online JSX compiler
  3. Babel: How to use the react transformer

元件還應該包括什麼

每個元件都應該包括一些內部狀態,處理邏輯,和事件處理器(例如按鈕點選、輸入改變), 當然也包括一些內部的樣式。

你會遇到{this.props.name}這樣的程式碼片段,這意味著你可以通過屬性的方式 先元件內傳遞資料,例如 <MyComp name='weiwei sun' /> 。這讓元件變得可重用, 並且能夠自上而下的向巢狀的元件傳遞資料。

示例程式碼如下:

 React擁抱ES6

在React中嘗試編寫ES6是個非常不錯的開始,React並不是一開始就支援ES6的, 而是從 v0.13.0 開始支援的。你會經常用到的ES6特性包括類、箭頭函式、consts 和模組。例如,我們會經常從繼承 React.Component 類開始編寫我們的元件。

還有一點需要注意的是,並不是每個瀏覽器都支援ES6,因此目前情況下,我們需要 使用一些工具將我們編寫的ES6程式碼轉換為ES5程式碼,我推薦使用Babel

一些參考資料:

  1. Babel: Learn ES6
  2. React ES6 announcement

元件生命週期

每個React元件在載入時都有特定的生命週期,在此期間不同的方法會被執行。 下面簡單介紹React元件的生命週期:

componentWillMount

該方法會在元件render之前執行,並且永遠只執行一次。

componentDidMount

該方法會在元件載入完畢之後立即執行。此時,元件已經完成了DOM結構的渲染, 並可以通過 this.getDOMNode() 方法來訪問。

componentWillReceiveProps

元件接收到一個新的prop時會被執行,且該方法在初始render時不會被呼叫。

shouldComponentUpdate

在元件接收到新的props或state時被執行。

componentWillUpdate

在元件接收到新的props或者state但還沒有render時被執行。 在初始化時不會被執行。

componentDidUpdate

在元件完成更新後立即執行。在初始化時不會被執行。 一般會在元件完成更新後被使用。

componentWillUnMount

在元件從DOM中unmount後立即執行。該方法主要用來執行一些必要的清理任務。

關於生命週期的具體內容,你可以參考官方文件

在打包時使用Webpack和Babel

我們會經常用到一些工具,首先一個是node.js的模組系統和它的包管理工具npm。 我們會編寫node風格的程式碼來require我們需要的東西。並且react本身也是一個獨立的 npm包。

通常你有兩種選擇,commonJS或者ES6:

或者

例如,我們會使用debug模組來除錯, 使用superagent模組來編寫請求。

現在,我們有了Node的依賴管理系統,並且使用npm來提供模組。下面我們需要做的 事:選擇一個合適的庫來打包我們的程式碼,並且能夠讓其執行在瀏覽器上。

因此我們需要一個打包器。目前最流行的解決方案包括兩個,分別是BrowserifyWebpack。我們選擇使用Webpack,因為Webpack 更適合於React社群。

Webpack是如何工作的

Webpack用於打包我們的程式碼,並且包含進我們需要的包,然後輸出為瀏覽器可執行的 檔案。因為我們使用JSXES6,因此我們需要相應的工具來將其轉換為ES5。事實上, Babel能夠同時做這兩件事。使用Webpack能夠很輕鬆的完成這些任務,因為Webpack 是面向配置的。

使用如下命令開始:

然後建立 webpack.config.js 檔案,我們需要使用ES5來編寫該檔案,因為它是 webpack的配置檔案。一個典型的配置方式如下:

執行 webpack 命令你可以執行打包流程。這之後你可以只在頁面中包含 bundle.js 即可。 如下:

(提示:你可以使用 node-static 來存放你的靜態資原始檔,使用 npm install -g node-static 來安裝,並使用 static .來啟動)。

專案結構

一個典型的專案結構你可以參考這個倉庫

 如何測試React元件

對於React元件的測試,這裡推薦使用Jest, Jest也是由Facebook提供的測試框架,並且有很多強大的特性,但這裡並會詳細的 介紹它們。

關於Jest,我推薦你閱讀和嘗試來自Facebook的Tutorial

對於ES6程式碼的測試,你可以參考 React ES6 Testing

小結

本文簡單介紹了React的基礎原理,一些相關的程式設計技術。後續還會整合一些資料 談一談Flux和同構。

Statement

本文翻譯自:https://blog.risingstack.com/the-react-way-getting-started-tutorial/ 有增刪改。

References

  1. https://blog.risingstack.com/the-react-way-getting-started-tutorial/
  2. https://github.com/RisingStack/react-way-getting-started
  3. http://facebook.github.io/react/docs/component-specs.html

相關文章