翻译 | 《JavaScript Everywhere》第12章 使用React构建Web客户端javascript
你们好呀,我是毛小悠,是一位前端开发工程师。正在翻译一本英文技术书籍。html
为了提升你们的阅读体验,对语句的结构和内容略有调整。若是发现本文中有存在瑕疵的地方,或者你有任何意见或者建议,能够在评论区留言,或者加个人微信:code_maomao,欢迎相互沟通交流学习。前端
(σ゚∀゚)σ..:*☆哎哟不错哦java
超文本背后的原始想法是获取相关文档并将它们连接在一块儿:若是学术论文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
的团队还开发了Angular
,Vue
,Scala.js
,Native iOS
和Native Android
集成。后端
尽管咱们将在本书中使用Apollo
,但它远远不是惟一一个GraphQL
客户端选项。Facebook
的Relay
和Formiddable
的urql
也是两个受欢迎的选择。
此外,咱们将使用parcel
做为咱们的代码捆绑器。代码捆绑器使咱们可使用Web
浏览器中可能不具有的功能(例如,较新的语言功能,代码模块,压缩)编写JavaScript
,并将其打包以供在浏览器环境中使用。Parcel
是Webpack
等应用程序构建工具的无配置替代方案。它提供了许多不错的功能,例如代码拆分和在开发过程当中自动更新浏览器(又称热模块替换),而无需创建构建。如上一章所述,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
文件,请尝试在文本编辑器中打开目录。该文件应该在编辑器的文件浏览器中可见。或者,在终端窗口中键入ls -a
将列出当前工做目录中的文件。
在本地克隆了启动代码以后,咱们就能够构建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
中,咱们首先导入react
和react-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> ); };
若是你只是从React
入手,你可能会想知道用标签包围组件的趋势。React
的组件必须包含于父元素,这每每是一种标签,但也能够是任何其余适当的HTML
标签,例如,,或.
若是感受包含HTML
的标记多余,咱们能够用空的<>标记在咱们的JavaScript
代码中包含这些组件。
最后,咱们将经过添加如下内容来指示React
在根ID
为root
的元素内渲染应用程序:
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.js
,mynotes.js
和favorite.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;
在前面的示例中,咱们使用React
的useEffect
钩子来设置页面标题。Effect
挂钩使咱们在组件中存在反作用,会更新与组件自己无关的内容。若是你有兴趣,能够深刻探讨React
的Effect hooks
文档。
如今,在src/pages/index.js
中,咱们将使用react-router-dom
包导入React Router
和Web
浏览器路由所需的方法:
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 Router
的Link
组件。
在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
视为由微小的组件组成是React
的核心功能之一,也是我在掌握框架方面的突破。
咱们将从为应用程序建立标题和导航组件开始。首先,让咱们在src
目录中建立一个名为components
的新目录。在src/components
目录中,咱们将建立两个名为Header.js
和Navigation.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 Router
的Link
功能并标记一个无序的连接列表。在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
向应用程序添加布局和样式。
若是有理解不到位的地方,欢迎你们纠错。若是以为还能够,麻烦您点赞收藏或者分享一下,但愿能够帮到更多人。