翻譯 | 《JavaScript Everywhere》第12章 使用React構建Web客戶端

翻譯 | 《JavaScript Everywhere》第12章 使用React構建Web客戶端javascript

寫在最前面

你們好呀,我是毛小悠,是一位前端開發工程師。正在翻譯一本英文技術書籍。html

爲了提升你們的閱讀體驗,對語句的結構和內容略有調整。若是發現本文中有存在瑕疵的地方,或者你有任何意見或者建議,能夠在評論區留言,或者加個人微信:code_maomao,歡迎相互溝通交流學習。前端

(σ゚∀゚)σ..:*☆哎喲不錯哦java

第12章 使用React構建Web客戶端

超文本背後的原始想法是獲取相關文檔並將它們連接在一塊兒:若是學術論文A引用學術論文B,讓咱們能夠輕鬆地單擊某些內容並在它們之間導航。1989年,CERN的一位名爲Tim Berners-Lee的軟件工程師提出了將超文本與聯網計算機相結合的想法,從而令人們能夠輕鬆地創建這些鏈接,而無論文檔的位置如何。每張貓的照片、新聞、推文、流媒體視頻、求職網站和餐廳評論都應歸功於全局連接文檔的簡單想法。react

從本質上講,網絡仍然是將文檔連接在一塊兒的媒介。在網絡瀏覽器中,每一個頁面都是HTML,帶有CSS(用於樣式設置)和JavaScript(用於加強功能)。今天,咱們使用這些技術來構建從我的博客和小型手冊站點到複雜的交互式應用程序的全部內容。其根本優勢是Web提供了通用訪問權限。任何人只須要一個能夠鏈接網絡的網絡瀏覽器,會建立一個默認的環境。git

咱們正在構建什麼

在接下來的章節中,咱們將爲社交筆記應用Notedly構建Web客戶端。用戶將可以建立和登陸賬戶,在Markdown中編寫筆記,編輯他們的筆記,查看其餘用戶筆記的摘要以及「收藏」其餘用戶筆記。爲此,咱們將與GraphQL服務器API進行交互。github

在咱們的Web應用程序中:web

  • 用戶將可以建立筆記、閱讀、更新和刪除他們建立的筆記。
  • 用戶將可以查看其餘用戶建立的筆記的摘要,並閱讀其餘人建立的單個筆記,儘管他們將沒法更新或刪除它們。
  • 用戶將可以建立賬戶,登陸和註銷。
  • 用戶將可以檢索其我的資料信息以及其餘用戶的公共我的資料信息。
  • 用戶將可以收藏其餘用戶的筆記以及檢索其收藏夾列表。

這些功能將涉及不少領域,可是在本書的這一部分中,咱們將把它們分紅小塊。一旦學會了使用全部這些功能構建React應用程序,就能夠將工具和技術應用於構建各類富Web應用程序。npm

咱們將如何構建它

你可能已經猜到了,要構建此應用程序,咱們將使用React做爲客戶端JavaScript庫。此外,咱們將從GraphQL API查詢數據。爲了幫助查詢,修改和緩存數據,咱們將使用Apollo客戶。Apollo Client包含用於使用GraphQL的一系列開源工具。咱們將使用庫的React版本,可是Apollo的團隊還開發了AngularVueScala.jsNative iOSNative Android集成。後端

其餘GraphQL客戶端庫

儘管咱們將在本書中使用Apollo,但它遠遠不是惟一一個GraphQL客戶端選項。FacebookRelayFormiddableurql也是兩個受歡迎的選擇。

此外,咱們將使用parcel做爲咱們的代碼捆綁器。代碼捆綁器使咱們可使用Web瀏覽器中可能不具有的功能(例如,較新的語言功能,代碼模塊,壓縮)編寫JavaScript,並將其打包以供在瀏覽器環境中使用。ParcelWebpack等應用程序構建工具的無配置替代方案。它提供了許多不錯的功能,例如代碼拆分和在開發過程當中自動更新瀏覽器(又稱熱模塊替換),而無需創建構建。如上一章所述,create-react-app它還提供了零配置的初始設置,在後臺使用Webpack,但Parcel容許咱們從頭開始構建應用程序,這是我發現學習的理想方式。

入門

在開始開發以前,咱們須要將項目啓動代碼文件複製到咱們的電腦上。

項目的源代碼包含咱們開發應用程序所需的全部腳本和對第三方庫的引用。要將代碼克隆到本地計算機,請打開終端,導航到保存項目的目錄,而後git clone項目存儲庫。若是你已經遍歷了API章節,則可能已經建立了一個notedly目錄來保持項目代碼的條理性:

# change into the Projects directory
$ cd
$ cd Projects
$ # type the `mkdir notedly` command if you don't yet have a notedly directory
$ cd notedly
$ git clone git@github.com:javascripteverywhere/web.git
$ cd web
$ npm install

安裝第三方依賴項

經過使用本書的入門代碼的副本並在目錄中運行npm install,你無需爲任何第三方依賴項再次運行npm install

該代碼的結構以下:

  • /src

這是你隨書一塊兒進行開發的目錄。

  • /solutions

該目錄包含每章的解決方案。若是你卡住了,這些能夠供你參考。

  • /final

該目錄包含最終的工做項目。

如今,你已經在電腦上安裝了代碼,複製項目的.env文件。這個文件保存了咱們特殊的工做環境變量。

例如,在本地工做時,咱們將指向API的本地實例,可是在部署應用程序時,咱們將指向咱們遠程的API。複製.env文件,從Web目錄在終端中鍵入如下內容:

$ cp .env.example .env

你如今應該看到一個.env文件。你無需對該文件作任何事情,可是隨着API後端的開發,咱們將向其中添加信息。項目附帶的.gitignore文件將確保你不會無心間提交.env文件。

求助,我看不到.env文件!

默認狀況下,操做系統隱藏以句點開頭的文件,由於這些文件一般由系統使用,而不是最終用戶使用。若是看不到.env文件,請嘗試在文本編輯器中打開目錄。該文件應該在編輯器的文件瀏覽器中可見。或者,在終端窗口中鍵入ls -a將列出當前工做目錄中的文件。

構建Web應用程序

在本地克隆了啓動代碼以後,咱們就能夠構建React Web應用程序了。首先讓咱們看一下src/index.html文件。這看起來像一個標準的但徹底爲空的HTML文件,但請注意如下兩行:

<div id="root"></div>
<script src="./App.js"></script>

這兩行對咱們的React應用程序很是重要。

root將提供整個應用程序的容器。同時,App.js文件將成爲咱們JavaScript應用程序的入口。

如今咱們能夠開始在src/App.js文件中開發React應用程序了。若是你跟隨上一章中的React簡介,可能會以爲很熟悉。在src/App.js中,咱們首先導入reactreact-dom庫:

import React from 'react';
import ReactDOM from 'react-dom';

如今,咱們將建立一個名爲App的函數,該函數將返回應用程序的內容。如今,這將只是元素中包含的兩行HTML

const App = () => {
return (
<div>
<h1>Hello Notedly!</h1>
<p>Welcome to the Notedly application</p>
</div>
);
};

和全部的div相關的是什麼?

若是你只是從React入手,你可能會想知道用標籤包圍組件的趨勢。React的組件必須包含於父元素,這每每是一種標籤,但也能夠是任何其餘適當的HTML標籤,例如,,或.

若是感受包含HTML的標記多餘,咱們能夠用空的<>標記在咱們的JavaScript代碼中包含這些組件。

最後,咱們將經過添加如下內容來指示React在根IDroot的元素內渲染應用程序:

ReactDOM.render(<App />, document.getElementById('root'));

如今,咱們的src/App.js文件的完整內容應爲:

import React from 'react';
import ReactDOM from 'react-dom';
const App = () => {
return (
<div>
<h1>Hello Notedly!</h1>
<p>Welcome to the Notedly application</p>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));

完成此操做後,讓咱們在Web瀏覽器中進行查看。經過在終端應用程序中鍵入npm run dev來啓動本地開發服務器。編譯代碼後,請訪問 http://localhost:1234來查看頁面(圖12-1)。

12-1咱們最初在瀏覽器中運行的React應用程序

路由

網絡的定義特徵之一是可以將文檔連接在一塊兒。一樣,對於咱們的應用程序,咱們但願用戶可以在屏幕或頁面之間導航。在HTML呈現的應用程序中,這將涉及建立多個HTML文檔。每當用戶導航到新文檔時,即便兩個頁面上存在共享的方面(例如頁眉或頁腳),整個文檔也會從新加載。

JavaScript應用程序中,咱們能夠利用客戶端路由。在許多方面,這將相似於HTML連接。用戶將單擊一個連接,URL將更新,而且他們將導航到新屏幕。不一樣之處在於咱們的應用程序只會使用更改後的內容來更新頁面。體驗將是「相似於應用程序的」的流暢,這意味着將不會看到頁面的刷新。

React中,最經常使用的路由庫是Router。這個庫使咱們可以向React Web應用程序添加路由功能。爲了將路由引入咱們的應用程序,讓咱們首先建立一個src/pages目錄並添加如下文件:

  • /src/pages/index.js
  • /src/pages/home.js
  • /src/pages/mynotes.js
  • /src/pages/favorites.js

咱們的home.jsmynotes.jsfavorite.js文件將成爲咱們單獨的頁面組件。咱們能夠爲每一個文件建立一些初始內容和效果鉤子,當用戶導航到頁面時,它們將更新文檔標題。

src/pages/home.js中:

import React from 'react';
const Home = () => {
return (
<div>
<h1>Notedly</h1>
<p>This is the home page</p>
</div>
);
};
export default Home;

src/pages/mynotes.js中:

import React, { useEffect } from 'react';
const MyNotes = () => {
useEffect(() => {
// update the document title
document.title = 'My Notes — Notedly';
});
return (
<div>
<h1>Notedly</h1>
<p>These are my notes</p>
</div>
);
};
export default MyNotes;

src/pages/favorites.js中:

import React, { useEffect } from 'react';
const Favorites = () => {
useEffect(() => {
// update the document title
document.title = 'Favorites — Notedly';
});
return (
<div>
<h1>Notedly</h1>
<p>These are my favorites</p>
</div>
);
};
export default Favorites;

useEffect

在前面的示例中,咱們使用ReactuseEffect鉤子來設置頁面標題。Effect掛鉤使咱們在組件中存在反作用,會更新與組件自己無關的內容。若是你有興趣,能夠深刻探討ReactEffect hooks文檔。

如今,在src/pages/index.js中,咱們將使用react-router-dom包導入React RouterWeb瀏覽器路由所需的方法:

import React from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';

接下來,咱們將導入剛剛建立的頁面組件:

import Home from './home';
import MyNotes from './mynotes';
import Favorites from './favorites';

最後,咱們將使用特定的URL指定咱們建立爲路由的每一個頁面組件。請注意,對於咱們的「Home」路由使用了徹底匹配,這將確保僅針對根URL呈現主頁組件:

const Pages = () => {
return (
<Router>
<Route exact path="/" component={Home} />
<Route path="/mynotes" component={MyNotes} />
<Route path="/favorites" component={Favorites} />
</Router>
);
};
export default Pages;

如今,咱們完整的src/pages/index.js文件應以下所示:

// import React and routing dependencies
import React from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
// import routes
import Home from './home';
import MyNotes from './mynotes';
import Favorites from './favorites';
// define routes
const Pages = () => {
return (
<Router>
<Route exact path="/" component={Home} />
<Route path="/mynotes" component={MyNotes} />
<Route path="/favorites" component={Favorites} />
</Router>
);
};
export default Pages;

最後,咱們能夠經過導入路由並渲染組件來更新src/App.js文件以使用咱們的路由:

import React from 'react';
import ReactDOM from 'react-dom';
// import routes
import Pages from '/pages';
const App = () => {
return (
<div>
<Pages />
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));

如今,若是你在Web瀏覽器中手動更新URL,則應該可以查看每一個組件。例如,鍵入http:// localhost:1234/favorites來呈現「收藏夾」頁面。

連接

咱們已經建立了頁面,可是缺乏將它們連接在一塊兒的關鍵部分。所以,讓咱們從首頁添加到其餘頁面的連接。爲此,咱們將使用React RouterLink組件。

src/pages/home.js中:

import React from 'react';
// import the Link component from react-router
import { Link } from 'react-router-dom';
const Home = () => {
return (
<div>
<h1>Notedly</h1>
<p>This is the home page</p>
{ /* add a list of links */ }
<ul>
<li>
<Link to="/mynotes">My Notes</Link>
</li>
<li>
<Link to="/favorites">Favorites</Link>
</li>
</ul>
</div>
);
};
export default Home;

這樣咱們就能夠瀏覽咱們的應用程序。
單擊主頁上的連接之一將導航到相應的頁面組件。
瀏覽器的核心導航功能(如後退和前進按鈕)也將繼續起做用。

UI組件

咱們已經成功建立了單個頁面組件,而且能夠在它們之間進行導航。在構建頁面時,它們將具備幾個共享的用戶界面元素,例如標題和站點範圍的導航。每次使用它們時重寫它們都不會很是高效(而且會很煩人)。取而代之的是,咱們能夠編寫可重用的接口組件,並將它們導入到咱們須要的任何地方。實際上,將咱們的UI視爲由微小的組件組成是React的核心功能之一,也是我在掌握框架方面的突破。

咱們將從爲應用程序建立標題和導航組件開始。首先,讓咱們在src目錄中建立一個名爲components的新目錄。在src/components目錄中,咱們將建立兩個名爲Header.jsNavigation.js的新文件。React組件必須大寫,所以咱們也將遵循大寫文件名的慣例。

讓咱們首先在src/components/Header.js中編寫標頭組件。爲此,咱們將導入logo.svg文件,併爲咱們的組件添加相應的標記:

import React from 'react';
import logo from '../img/logo.svg';
const Header = () => {
return (
<header> <img src={logo} alt="Notedly Logo" height="40" /> <h1>Notedly</h1> </header> );
};
export default Header;

對於咱們的導航組件,咱們將導入React RouterLink功能並標記一個無序的連接列表。在src/components/Navigation.js中:

import React from 'react';
import { Link } from 'react-router-dom';
const Navigation = () => {
return (
<nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/mynotes">My Notes</Link> </li> <li> <Link to="/favorites">Favorites</Link> </li> </ul> </nav>
);
};
export default Navigation;

在屏幕截圖中,你會發現我還包括了表情符號字符做爲導航圖標。

若是你要這樣作,包含表情符號字符的可訪問標記以下:

<span aria-hidden="true" role="img">
<!-- emoji character --> </span>

完成標題和導航組件後,咱們如今能夠在應用程序中使用它們了。讓咱們更新src/pages/home.js文件以包含這些組件。咱們將首先導入它們,而後將組件包括在咱們的JSX標記中。

咱們的src/pages/home.js如今將以下所示(圖12-2):

import React from 'react';
import Header from '../components/Header';
import Navigation from '../components/Navigation';
const Home = () => {
return (
<div> <Header /> <Navigation /> <p>This is the home page</p> </div>
);
};
export default Home;

12-2使用React組件,咱們能夠輕鬆地組合可共享的UI功能。

這是咱們可以在咱們的應用程序中建立可共享組件所需的一切。有關在UI中使用組件的更多信息,我強烈建議閱讀React文檔頁「「Thinking in React」.

結論

網絡仍然是分發應用程序的無比重要的媒介。它使開發者能夠實時更新訪問。

在本章中,咱們在React中構建了JavaScript Web應用程序。在下一章中,咱們將使用React組件和CSS-in-JS嚮應用程序添加布局和樣式。

若是有理解不到位的地方,歡迎你們糾錯。若是以爲還能夠,麻煩您點贊收藏或者分享一下,但願能夠幫到更多人。

相關文章
相關標籤/搜索