如何在已有的 Web 應用中使用 ReactJS


原文:How to Sprinkle ReactJS into an Existing Web Application

譯者:nzbin

當我們學習一項新技術,可能是一個 JavaScript 框架,也可能是一個 CSS 方法,我們將面對這樣的挑戰 如何在舊網站上運用這項新技術?。很多教程講述了如何從頭開始,但卻很難運用到實際工作中。

在這篇教程中,我會通過一些很基本的例子講解如何靈活運用 ReactJS,以及替換使用 jQuery 寫的代碼。

從 jQuery 到 React

我最近的任務是用 React 重構一個使用 jQuery 寫的功能。這個過程困難重重,因為大量的 jQuery 分散在代碼段中。使用 jQuery 構建所有的 UI 是可能的(我們已經這樣做了很多年),但是在規模變大之后,將變得混亂且難以維護。

無論你使用 Angular, Ember, Vue, React, 或者只是 jQuery,你所做的事情和開發者多年來所做的事情是一樣的:

渲染 HTML > 接收用戶事件 > 重新渲染 HTML

因為 jQuery 非常依賴選擇器比如  .classes#IDs 去控制 DOM,所以大量的屬性會使 HTML 變得容易混淆,而這些屬性的目的只是方便 jQuery 查找。如果代碼量比較小,這是沒有問題的, 但是如果代碼量龐大,就會很難知道哪些類用於 CSS,哪些類用於 JavaScript。如果你之前為了改變一個功能而在 HTML 模板或 JavaScript 中查找 find 一個 .class 或者 #ID 選擇器,你應該明白我說的。

過渡依賴 .classes#IDs 的選擇來操縱 HTML 並不輕松。

所以,如果你的代碼是用 jQuery 或者其它框架所寫,那么應該如何使用 React 去替換這些 UI 片段?

開始之前應該了解的事情

Wrapper / Container 元素

無論使用 jQuery 還是下一個流行框架開發應用,大多數情況都是用一個根元素包裹 UI 片段。如果代碼庫使用 jQuery,通常會有一個元素充當 wrapper 選擇器。使用 jQuery 選擇 wrapper 元素,它被用於動態更新 DOM。

<!-- 
  .MyAwesomeFeature acts as a container to select 
  and manipulate child components with jQuery.
-->
<div class="MyAwesomeFeature">
  <div class="MyAwesomeFeature__title"></div>
  <div class="MyAwesomeFeature__image"></div>
</div>

<script>
  var container = $(".MyAwesomeFeature");
  $(".MyAwesomeFeature__title", container).text("Hello World!");

  // Other DOM changes, event handlers, etc...
</script>

獨立狀態 vs. 共享狀態

可以看一下你的應用中的功能狀態是獨立 isolated 於 container 元素還是在多個元素中共享 shared

相關教程: Getting Started with React

  1. 獨立狀態 -  這種狀態獨立存在於 container 元素中。所有按鈕、輸入框等的交互狀態都由這個 wrapper / container 元素分享。

  2. 共享狀態 - 這種狀態由多個元素共享。比如,從頁面其它位置的日期下拉框中更新日歷。 菜單和日歷在不同的容器中,但是它們的狀態是共享的。

我將用 jQuery 和 ReactJS 做的 4 個例子解釋共享/獨立狀態的概念。

用 jQuery 實現獨立狀態

假設我們有一個 web 應用,它展示了一個 emoji,當點擊按鈕,會隨機展示一個新的 emoji。下面的代碼是一個典型的 jQuery 應用,我們選擇父級元素 .mood-container ,然后動態改變內容。

以下是例子 的 HTML:

<!--
    Demonstrates how jQuery can be used to 
    use a container as a selector and update 
    the content within.
-->
<div id="mood-container">
  <div class="Mood">
    <div class="Mood__emoji"></div>
    <div class="Mood__name">[ Emoji Placeholder ]</div>
    <button class="Mood__button">Random Mood</button>
  </div>
</div>

See the Pen Isolated state with jQuery by Andrew Del Prete (@andrewdelprete) on CodePen.

這並不是使用 jQuery 更改 DOM 的唯一策略,但很常見。

用 ReactJS 實現獨立狀態

使用如 React 的庫的好處之一就是可以將上面的 JavaScript 和 HTML 封裝成一個組件 component 。它是一個更可靠、可維護、可重用的功能部件。

這在處理大型應用時非常有用,因為組件 component 的渲染和更新是同步的。我並不是指將關注點與邏輯和視圖層混合在一起,而是如何將 JavaScript 和 HTML 以組件 component 的形式組織代碼。這是所有 JavaScript 框架的共同理念,因此被稱為 Framework

所有框架通常都是:

  1. 掛載到特殊的容器 container上 ( 比如 App 中名為 #ID 的 div )。
  2. 向容器 container 中渲染內容。
  3. 負責跟蹤和更新容器 container 中的內容。
  4. 負責移除容器 container 中的內容。

以下是使用 React 整合后的新的 HTML:

<!--
    Demonstrates how ReactJS mounts itself 
    to a container and takes it from there.
-->
<div id="mood-container" />

See the Pen Isolated state with ReactJS by Andrew Del Prete (@andrewdelprete) on CodePen.

用 jQuery 實現共享狀態

使用 jQuery 可以很容易實現,但是,如果一個區域動態影響另一個單獨使用選擇器的區域時,可能會變得混亂。另外,當你使用 .classes 以及 #IDs 作為選擇器手動控制 DOM 的時候,你要負責跟蹤所有事情的開銷。

See the Pen Shared state with jQuery by Andrew Del Prete (@andrewdelprete) on CodePen.

在這個例子中,我們通過 .Mood__name.Mood__button-name 選擇器分享 mood name ,並且通過一個容器中的按鈕去更新另一個容器中的 emoji 。這還可以寫的更簡單一些,但是不管怎樣,當嘗試用 jQuery 選擇器單獨管理所有這些事情時,就會變得很糟糕。

用 ReactJS 實現共享狀態

在 ReactJS 中,通常有兩個分享組件狀態的方法:

  1. 將組件包裹在 container 元素中去管理狀態,將數據/函數作為 props 向組件傳遞。
  2. 使用類似 Redux 的工具在全局定義狀態和 actions,然后將組件掛載上去。

使用 Container 分享狀態

這是使用  React 渲染比較常見的方式,尤其 SPA 應用或者 UI 片段。因為我們希望組件之間通信,所以我們將它們放置在父級組件中,然后向下傳遞屬性來更新每個子組件。這是 ReactJS 最基本的工作方式。

這種方式適用於多個 UI 組件被一個父組件包裹的情況。很多之前創建的應用可能不適合,但是可以根據 UI 布局情況選擇使用。

See the Pen Shared state with ReactJS - Container by Andrew Del Prete (@andrewdelprete) on CodePen.

使用 Redux 分享狀態

類似 Redux(flux 的另一種實現)的庫可以很容易的實現應用中不同組件之間的通信。可以將 actions 和狀態屬性掛載到組件,通過更新全局對象 Redux 來分享狀態。

See the Pen Shared state with ReactJS - Redux by Andrew Del Prete (@andrewdelprete) on CodePen.

總結

我希望這篇文章可以讓你更好地了解需要關注的內容以及如何將 ReactJS 運用到現有的應用中。主要的解決方法就是,如果你使用 jQuery 處理 UI 片段,那么你可以將容器元素替換成一個 React 組件。如果你需要在多個組件中分享狀態,那么你可以使用容器方法或者類似 Redux 的庫。

感謝閱讀!

-Andrew Del Prete


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM