成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

用React Router 4構(gòu)建通用JavaScript應用

開發(fā) 前端
React Router 是一個在 React 領(lǐng)域非常流行的庫。它依靠位置欄上的請求 URL 和 瀏覽器的操作歷史來渲染不同的頁面內(nèi)容來保持顯示,進而將你的 app 同步到用戶接口的頁面上。

React Router 是一個在 React 領(lǐng)域非常流行的庫。它依靠位置欄上的請求 URL 和 瀏覽器的操作歷史來渲染不同的頁面內(nèi)容來保持顯示,進而將你的 app 同步到用戶接口的頁面上。

[[185175]]

新的閃閃發(fā)亮

最近,版本4的 React Router 已經(jīng)進入 beta 發(fā)布階段。損譽各半,React Router 的這一次發(fā)布是對上一版本的完整重寫,這導致了很多破壞性的 API 變更。

在版本 4 的核心理念是 “聲明式可組合性(declarative composability)”?—— 它包含 React 之所以優(yōu)秀的組件概念,并將其應用于 routing。React Router 4 的每一個部分都是 React 的組件: Router ,  Route ,  Link 等等。

React Router 的一位開發(fā)者, Ryan Florence ,親手制作了一個簡短的視頻來介紹***的 React Router,這段視頻獲得了很多人的推薦:

視頻: https://youtu.be/a4kqMQorcnE

后臺如何?

新版本的 React Router 奉上了一個新的 web 頁面,上面有 許多實用的代碼示例 ,但沒有提供實例介紹如何在服務(wù)端使用 React Router 來進行基于 React 的頁面的渲染。

對于我近期正在進行的項目,對搜索引擎友好且具備***的網(wǎng)站運行速度是重中之重,難道這樣就要在客戶端渲染整個頁面?難道就用示例頁面上所有實例所采取的辦法?那是不可取的。我們要使用一個 Express 服務(wù)器來在后臺對 React 頁面進行渲染。

在其介紹視屏中, Ryan 有一個可以從某些 API 獲取數(shù)據(jù)來初始化其狀態(tài)的 App 組件, 使用的是 componentDidMount 生命周期方法。但異步數(shù)據(jù)的獲取操作完畢,組件就會被更新以顯示數(shù)據(jù)。

但是當要在服務(wù)端對 App 組件進行渲染的時候這樣做不會有效果: 在你使用 renderToString 的時候, 帶有 HTML 代碼的字符串在調(diào)用了組件的渲染方法之后就會被同步地創(chuàng)建出來。 componentDidMount 從未被調(diào)用到。

因此如果我們使用 Ryan 視頻里的示例在后臺渲染出 App 組件,它只會生成一條 “Loading…” 消息。

解決方案

作為對概念方案的驗證,我創(chuàng)建了一個 demo 應用,基本上就是對視頻中 Ryan 的示例進行重造,但采取的是服務(wù)器端的渲染。

應用使用了 GitHub API 去獲取有關(guān)于 Gist 代碼片段的數(shù)據(jù):

 

代碼展示

你可以在 Github 上找到 demo 應用的源代碼:

https://github.com/technology-ebay-de/universal-react-router4

簡而言之,下面就是我所做的事情…

server/index.js

這就是每次有 HTTP 請求發(fā)到 Express 服務(wù)器的時候都會跑一次的代碼:

const routes = [
    '/',
    '/g/:gistId'
];

app.get('*', (req, res) => {
    const match = routes.reduce((acc, route) => matchPath(req.url, route, { exact: true }) || acc, null);
    if (!match) {
        res.status(404).send(render(<NoMatch />));
        return;
    }
    fetch('https://api.github.com/gists')
        .then(r => r.json())
        .then(gists => 
            res.status(200).send(render(
                (
                    <StaticRouter context={{}} location={req.url}>
                        <App gists={gists} />
                    </StaticRouter>
                ), gists
            ))
        ).catch(err => res.status(500).send(render(<Error />));
});

app.listen(3000, () => console.log('Demo app listening on port 3000'));

(注意:這里只是摘錄,你可以在  GitHub  找到完整的源代碼 )

在第 1–4行 , 我為 app 定義了一個路由數(shù)組。數(shù)組的***個元素就是針對主頁的初始請求, 沒有 Gists 被選上。第二個路由就是用來展示一個被選上的 Gist 的。

在第 6行 , 我的 Express app 被告知要處理任何可以使用星號匹配上的請求。

在第 7行 , 我使用了來自于 React Router 的  matchPath 函數(shù)對路由數(shù)組進行簡省; 結(jié)果就是一個匹配對象,其擁有關(guān)于能匹配到的路由以及任何可以從 URL 路徑轉(zhuǎn)換過來的參數(shù),這些信息。

在第 8–11行 , 如果有不能匹配的路由,我就渲染出一個錯誤頁面,上面會說 : “頁面沒找到(Page not found)”。

這里的 render 函數(shù)只是圍繞 React 的  renderToString 的一個封裝而已,添加了包圍 React 組件的 HTML 的基礎(chǔ)頁面的 HTML 代碼 ( <html><head><body> , 等等)。

在第 12–22行 , 我會從 GitHub API 獲取到可以填充 App 狀態(tài)的數(shù)據(jù),并且對 App 組件進行渲染。

最顯而易見是第 17 行,我使用了 StaticRouter 組件來初始化 React Router。該 Router 組件類型是采用服務(wù)端渲染方案的***選擇。它永遠不會改變位置, 這是我們在本場景下所需要的, 因為是在后臺上, 我們只會渲染一次,而且不會直接地對用戶的交互操作做出反應。

而第 23 行 會捕獲在處理期間產(chǎn)生的錯誤信息來渲染出一個錯誤頁面。

我的 App 組件看起來像下面這樣:

export default ({ gists }) => (
    <div>
        <Sidebar>
            {
                gists ? gists.map(gist => (
                    <SidebarItem key={gist.id}>
                        <Link to={`/g/${gist.id}`}>
                            {gist.description || '[no description]'}
                        </Link>
                    </SidebarItem>
                )) : (<p>Loading…</p>)
            }
        </Sidebar>
        <Main>
            <Route path="/" exact component={Home} />
            {
                gists && (
                    <Route path="/g/:gistId" render={                         ({ match }) => (
                            <Gist gist={gists.find(g => g.id === match.params.gistId)} />
                        )
                    } />
                )
            }
        </Main>
    </div>
);

(→  GitHub上有完整的源代碼 )

在第 1 行 , 組件接收到作為一個屬性的 Gist 數(shù)據(jù)對象。

第 3–13行 渲染了一個  Sidebar 組件,里面是連接到不同 Gist 鏈接。  SidebarItem 組件里面所包含的是只有在存在實際的 Gist 數(shù)據(jù)時才會被渲染的數(shù)據(jù)。在服務(wù)端,總會有這樣的情況發(fā)生。而我們在服務(wù)端和客戶端渲染中都會用到該組件。如果組件是在客戶端被渲染的, 我們可能處在獲取新的 Gist 數(shù)據(jù)這一過程之中,所以會展示出一條 “Loading…(加載中)” 的消息。

第 15行 使用了一個來自于 React Router 庫的  Route 組件,用以在路由匹配到“/”這個路徑的時候展示出  Home 組件。這里我們使用的是精確匹配, 不然的話任何以斜線開頭的路徑都會匹配到。

如果有 Gist 數(shù)據(jù)要展示的話, 那么在第 18 行 , 另外一個 Route 組件就會被用來展示一個  Gist 組件,上面是被選擇的 Gist 的詳細信息。

client/index.js

如前所述,這是一個 通用 JavaScript 應用(大家都知道的“同構(gòu)”),意思是相同的代碼即可用于渲染服務(wù)器頁面,又可以用于渲染客戶端頁面。這里摘錄了一段在客戶端初始化頁面的代碼:

render((
    <BrowserRouter>
        <App gists={window.__gists__} />
    </BrowserRouter>
), document.getElementById('app'));

(→  GitHub 上的完整代碼 )

這比服務(wù)端代碼簡單多了! 第 1 行 的  render 函數(shù)就是  ReactDOM 的 render 函數(shù) 。它把我的 React 組件渲染出來的布局附加到 DOM 節(jié)點上。

第 2 行 使用了  BrowserRouter (代替了我在服務(wù)端進行渲染使用的 StaticRouter)。

第 3 行 我使用 gist 數(shù)據(jù)對 App 組件進行實例化,以此代替通過 GitHub API 獲取數(shù)據(jù)。gist 數(shù)據(jù)來自瀏覽器 DOM 的全局變量,它是后端通過 <script> 標簽放在那里的。

基本上就這些了!

當我需要在瀏覽器中打開應用程序時,我可以點擊側(cè)邊欄中的任何 Gist。客戶端的 Reactor 路由確保每次點擊鏈接時,頁面的網(wǎng)址都會更新,并且依賴于新網(wǎng)址的網(wǎng)頁部分會刷新。 當我點擊瀏覽器的重載按鈕時,后端的靜態(tài)路由確保顯示與之對應的數(shù)據(jù)頁面。

責任編輯:張燕妮 來源: 開源中國社區(qū)
相關(guān)推薦

2016-10-31 11:26:13

ReactRedux前端應用

2020-07-28 07:27:07

Vue前端Jquery

2016-11-01 21:02:47

javascriptreact.jsreact-route

2020-09-02 11:43:24

開發(fā)技能代碼

2016-07-01 14:43:32

DockerServerless

2024-05-15 11:42:33

FlutterWeb 庫應用程序

2022-08-15 17:34:22

react-routv6

2021-10-11 14:28:25

TypeScript企業(yè)級應用

2021-11-16 14:25:38

JavaScript前端

2009-11-23 19:42:57

ibmdwmashup

2022-09-13 09:02:19

React客戶端服務(wù)端

2019-05-27 13:50:35

多云架構(gòu)企業(yè)多云集成云計算

2021-07-14 17:39:46

ReactRails API前端組件

2023-09-04 08:32:43

web開發(fā)圖像

2015-04-20 15:26:12

2021-09-18 09:00:00

區(qū)塊鏈應用JavaScript

2018-10-15 10:22:51

2024-04-08 10:18:49

React前端TypeScript

2024-02-26 08:04:38

ReactReact.js場景

2015-03-30 12:13:23

React NativiOS
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 亚洲一区视频在线 | 中文字幕日韩在线 | 国产精品69毛片高清亚洲 | 国产99精品| 亚洲视频免费播放 | 日韩av在线免费 | 欧美一区二区免费 | 日韩在线观看 | 欧洲一区在线观看 | 黄色大片观看 | 在线观看国产www | 日韩欧美一区在线 | 国产在视频一区二区三区吞精 | 亚洲狠狠丁香婷婷综合久久久 | 免费的一级视频 | 99久久精品一区二区毛片吞精 | 国产成人麻豆免费观看 | h视频在线播放 | 成人黄色三级毛片 | 国产激情精品视频 | 午夜天堂精品久久久久 | 欧美一级大片 | 国产精品美女久久久久aⅴ国产馆 | 精品一区二区在线观看 | 久久久久久国产精品久久 | 九九精品在线 | 国产精品久久久久久久久久不蜜臀 | 久久久久久久久久久久91 | 密色视频 | 欧美簧片 | av在线电影网站 | 日日摸夜夜添夜夜添特色大片 | 亚洲国产一区二区三区在线观看 | 亚洲一区二区在线视频 | 国产成人精品免费视频大全最热 | 91久久精品一区二区二区 | 国产美女视频黄a视频免费 国产精品福利视频 | 天堂资源最新在线 | 欧美激情视频一区二区三区免费 | 中文在线一区 | 亚洲欧美国产一区二区三区 |