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

使用 React-Router 創(chuàng)建單頁(yè)應(yīng)用

開發(fā) 前端
在傳統(tǒng)的網(wǎng)頁(yè)應(yīng)用架構(gòu)中,客戶端只是一個(gè)展示層,通過(guò) url 訪問(wèn)服務(wù)端,服務(wù)端則根據(jù)自己的“路由表”將對(duì)應(yīng)的頁(yè)面分發(fā)給客戶端。但是在這種模式下,ajax 異步加載的內(nèi)容是無(wú)法通過(guò)url 記錄的。無(wú)論你在頁(yè)面上操作了多少,異步請(qǐng)求了多少數(shù)據(jù),在每次重新訪問(wèn)同一個(gè) url 時(shí),服務(wù)端返回給客戶端的內(nèi)容都是一模一樣。

最近業(yè)余時(shí)間在學(xué)習(xí) React,配合 Redux 和 React-Router 正在不緊不慢地開發(fā)一個(gè)小工具moviemaster,用于管理硬盤中的電影劇集。在單頁(yè)應(yīng)用開發(fā)中,redux 并不是必須的,所以今天只講講 前端的路由系統(tǒng)以及 React-Router的簡(jiǎn)單使用。

什么是路由

以下來(lái)自維基百科::

路由(routing)就是通過(guò)互聯(lián)的網(wǎng)絡(luò)把信息從源地址傳輸?shù)侥康牡刂返幕顒?dòng)。路由發(fā)生在OSI網(wǎng)絡(luò)參考模型中的第三層即網(wǎng)路層。路由引導(dǎo)分組轉(zhuǎn)送,經(jīng)過(guò)一些中間的節(jié)點(diǎn)后,到它們***的目的地。

這是網(wǎng)絡(luò)工程中的術(shù)語(yǔ),對(duì)大家而言,最熟悉的應(yīng)該就是家里的路由器。路由是指路由器從一個(gè)接口上收到數(shù)據(jù)包,根據(jù)數(shù)據(jù)包的目的地址進(jìn)行定向并轉(zhuǎn)發(fā)到另一個(gè)接口的過(guò)程。放在 Web 上來(lái)說(shuō),url 就像是路由器中的路由表,每個(gè) url 對(duì)應(yīng)不同的頁(yè)面或者內(nèi)容,就像路由表中的的 IP 對(duì)應(yīng)不同的網(wǎng)絡(luò)一樣。

先來(lái)看一下熟悉的套路:

在傳統(tǒng)的網(wǎng)頁(yè)應(yīng)用架構(gòu)中,客戶端只是一個(gè)展示層,通過(guò) url 訪問(wèn)服務(wù)端,服務(wù)端則根據(jù)自己的“路由表”將對(duì)應(yīng)的頁(yè)面分發(fā)給客戶端。但是在這種模式下,ajax 異步加載的內(nèi)容是無(wú)法通過(guò)url 記錄的。無(wú)論你在頁(yè)面上操作了多少,異步請(qǐng)求了多少數(shù)據(jù),在每次重新訪問(wèn)同一個(gè) url 時(shí),服務(wù)端返回給客戶端的內(nèi)容都是一模一樣。

如果前端有自己專屬的“路由表”來(lái)分發(fā)頁(yè)面上不同的狀態(tài),那不就行了?

Hash 和 pushState

據(jù)我所知,目前有兩種方式可以構(gòu)建出前端的路由系統(tǒng):url 中的#和 HTML5中的 history API。其原理如下:

  • 阻止標(biāo)簽的默認(rèn)跳轉(zhuǎn)動(dòng)作。
  • ajax或者 Fetch 請(qǐng)求內(nèi)容。
  • 將返回的內(nèi)容添加到頁(yè)面中。
  • 使用 hash 或者 pushState 修改 url。

經(jīng)典的 Hash

#代表網(wǎng)頁(yè)中的一個(gè)位置。后面接著的字符,就是該位置的標(biāo)識(shí)符。比如,

  1. https://zhanglun.github.io/index.html#body 

就代表網(wǎng)頁(yè) index.html 的 body 位置。瀏覽器讀取這個(gè) URL 后,會(huì)自動(dòng)將body位置滾動(dòng)至可視區(qū)域。標(biāo)識(shí)符的指定有兩個(gè)方法。

1. 使用錨點(diǎn)

  1. <a name="body"></a> 

2. 使用id屬性

  1. <div id="body" > 

#是用來(lái)指向文檔的內(nèi)容,屬于瀏覽器的行為,與服務(wù)端無(wú)關(guān),在 HTTP請(qǐng)求中也不會(huì)攜帶 #及其后面的內(nèi)容,對(duì)于服務(wù)端而言http://www.baidu.comhttp://www.baidu.com#action=fuckbaidu 返回給客戶端的都是前者所分發(fā)的內(nèi)容,但是在瀏覽器中可以通過(guò) Window 對(duì)象上的 location.hash 進(jìn)行操作。因此,在瀏覽器中可以通過(guò) hash 來(lái)記錄頁(yè)面的狀態(tài),構(gòu)建“路由表”。當(dāng)頁(yè)面狀態(tài)發(fā)生變化時(shí),hash 相應(yīng)變化,重新加載時(shí)又可以通過(guò) url 中攜帶的 hash 直接將頁(yè)面設(shè)置到對(duì)應(yīng)的狀態(tài)。

比如:

  1. http://www.example.com/ 
  2. http://www.examplt.com/#edit 
  3. http://www.examplt.com/#settings  
  1. 訪問(wèn)/時(shí),呈現(xiàn)主頁(yè)。
  2. 點(diǎn)擊頁(yè)面上的Edit按鈕,頁(yè)面呈現(xiàn)編輯對(duì)應(yīng)的內(nèi)容。通過(guò) url 直接訪問(wèn)時(shí),檢查 hash 是否和 edit 匹配,如果匹配執(zhí)行加載編輯內(nèi)容的代碼
  3. 點(diǎn)擊頁(yè)面上的Settings按鈕,頁(yè)面呈現(xiàn)設(shè)置對(duì)應(yīng)的內(nèi)容。通過(guò) url 直接訪問(wèn)時(shí),檢查 hash 是否和 settings 匹配,如果匹配執(zhí)行加載編輯內(nèi)容的代碼。

以下是偽代碼:

  1. function hashHandler () { 
  2.     let key = location.hash.slice(1); 
  3.     switch(key) { 
  4.       case 'edit'
  5.         renderEditPanel(); 
  6.         break; 
  7.       case 'settings'
  8.         renderSettings(); 
  9.         break; 
  10.        default
  11.         break; 
  12.     } 
  13.   } 
  14.   window.onload = () => { 
  15.     hashHandler(); 
  16.   } 
  17.   window.onhashchange = () => { 
  18.     hashHandler(); 
  19.   }  

HTML5 中的 pushState

pushState是 History API中的一個(gè)方法,其文檔可以看這里 MDN History。它的功能簡(jiǎn)單的說(shuō)就是:修改 url,添加歷史記錄。比如/blogs和settings對(duì)應(yīng)的是兩個(gè)頁(yè)面,如果只是在頁(yè)面上點(diǎn)擊標(biāo)簽切換,需要做的操作只有:發(fā)送請(qǐng)求修改頁(yè)面內(nèi)容和調(diào)用 pushState 方法修改 url。問(wèn)題來(lái)了,對(duì)于前端而言需要將其視為同一個(gè)頁(yè)面,但實(shí)際上這兩個(gè) url 對(duì)于服務(wù)端來(lái)說(shuō)是兩個(gè)不同的請(qǐng)求,所以這里需要服務(wù)端的配合。

我的做法是:對(duì)應(yīng)的url 返回的都是同一個(gè)頁(yè)面,然后瀏覽器接受之后檢查前端定義路由系統(tǒng),執(zhí)行響應(yīng)的代碼。這個(gè)方法可能會(huì)造成頁(yè)面平白添加一個(gè)短暫的延遲,不過(guò)影響不是很大。

React-Router的使用

目前來(lái)說(shuō),任何一個(gè)路由系統(tǒng)庫(kù)或者框架,雖說(shuō)是寫法不一,但是都是在上述兩種方式的基礎(chǔ)上實(shí)現(xiàn)的。讓我覺得耳目一新的是:使用路由嵌套的概念來(lái)定義 view 的嵌套集合,當(dāng)一個(gè)給定的 URL 被調(diào)用時(shí),整個(gè)集合中(***的部分)都會(huì)被渲染。

  1. import React from 'react'
  2. import { render } from 'react-dom'
  3. import { Router, Route, IndexRoute, hashHistory } from 'react-router'
  4.  
  5. import App from './containers/App'
  6. import MovieContainer from './containers/Movies'
  7. import Detail from './containers/Detail'
  8.  
  9.  
  10. let rootElement = document.getElementById('app'); 
  11. render( 
  12.   <Router> 
  13.     <Route path="/" component={App}> 
  14.       <Route path="about" component={About} /> 
  15.       <Route path="inbox" component={Inbox}> 
  16.         <Route path="messages/:id" component={Message} /> 
  17.       </Route> 
  18.     </Route> 
  19.   </Router>, 
  20. rootElement);  

在入口文件中,引入 React-Router,以組件的形式在 render 中使用,上述代碼配置結(jié)果如下: 

URL 組件
/ App
/about App -> About
/inbox App -> Inbox
/inbox/messages/:id App -> Inbox -> Message

在路由中,組件對(duì)應(yīng)設(shè)置的子組件可以通過(guò) this.props.children 渲染在父組件中

  1. class App extend Component { 
  2.   constructor(props) { 
  3.     super(props) 
  4.   } 
  5.   render() { 
  6.     <div id="app"
  7.       <h1>Hello, world!</h1> 
  8.       {this.props.children} 
  9.     </div> 
  10.   } 
  11.  

當(dāng) URL 為 / 時(shí), App 中并沒有渲染任何的組件,render 中的 this.props.children 還是 undefined。此時(shí)可以使用 IndexRoute 來(lái)設(shè)置一個(gè)默認(rèn)頁(yè)面。

  1. render( 
  2.   <Router> 
  3.     <Route path="/" component={App}> 
  4.       {/* 當(dāng) url 為/時(shí)渲染 Welcome */} 
  5.       <IndexRoute component={Welcome} /> 
  6.       <Route path="about" component={About} /> 
  7.       <Route path="inbox" component={Inbox}> 
  8.         <Route path="messages/:id" component={Message} /> 
  9.       </Route> 
  10.     </Route> 
  11.   </Router>, 
  12. rootElement);  
URL 組件
/ App -> Welcome
/about App -> About
/inbox App -> Inbox
/inbox/messages/:id App -> Inbox -> Message

此時(shí)匹配的路由分別是:/posts,/posts/usres/:userid 和/posts/users/:userid/messages/:messageid,可以看出,嵌套的<Route>所匹配的 url是包裹著它的 <Route>的 path “之和”。但是問(wèn)題又來(lái)了,嵌套的好處在于路由之間結(jié)構(gòu)清晰直觀,但是也會(huì)導(dǎo)致 url 的不美觀,試想/posts/users/:userid/messages/:messageid這么長(zhǎng)的路由也是著實(shí)讓人心累。React-Router 的配置提供了一個(gè)選擇:將 Route 的 path 設(shè)置成絕對(duì)路徑。同時(shí)可以使用<Redirect/> 將修改為絕對(duì)路徑的路由重定向到之前的設(shè)置

  1. <Route path="posts" component={Post}> 
  2.   <Route path="users/:userid" component={User}> 
  3.     <Route path="messages/:messageid" component={Message} /> 
  4.   </Route> 
  5. </Route>  
URL 組件
/posts App -> Post
/user/:userid App -> Post -> User
/messages/:messageid App -> Post -> User ->Message

基礎(chǔ)的配置完成之后,通過(guò) <Link>自動(dòng)或者通過(guò)browserHistory和hashHistory手動(dòng)執(zhí)行路由的跳轉(zhuǎn)。

責(zé)任編輯:龐桂玉 來(lái)源: segmentfault
相關(guān)推薦

2016-10-31 11:26:13

ReactRedux前端應(yīng)用

2022-08-15 17:34:22

react-routv6

2020-03-20 10:25:41

React-Routev6前端

2014-06-26 09:36:02

Angular評(píng)論應(yīng)用

2017-03-13 16:30:50

React Route構(gòu)建JavaScript

2018-08-26 22:39:08

單頁(yè)應(yīng)用HATEOAS

2016-11-28 09:13:29

單頁(yè)Web模板數(shù)據(jù)

2023-11-27 08:24:57

FormikReact

2016-09-07 15:35:06

VueReact腳手架

2014-09-09 10:49:59

AngularJS單頁(yè)應(yīng)用

2021-04-26 18:48:48

微應(yīng)用React

2022-09-13 09:02:19

React客戶端服務(wù)端

2021-06-01 09:27:52

視頻動(dòng)畫Remotion

2022-04-14 08:00:00

Cypress測(cè)試開發(fā)

2020-11-02 11:33:52

ReactVue應(yīng)用

2014-09-19 10:54:47

用戶體驗(yàn)單頁(yè)面

2020-03-27 09:20:00

單頁(yè)應(yīng)用程序網(wǎng)頁(yè)設(shè)計(jì)SPAs

2019-03-13 09:00:00

Web應(yīng)用SPAJavaScript

2020-10-27 12:07:17

DevOps單頁(yè)應(yīng)用程序開發(fā)

2025-04-03 00:45:00

點(diǎn)贊
收藏

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

主站蜘蛛池模板: 在线中文av| 成人在线观看中文字幕 | 亚洲欧美视频一区 | 免费小视频在线观看 | 国产99久久精品一区二区永久免费 | 2021天天躁夜夜看 | 精品一区二区三区91 | avav在线看 | 91久久夜色 | 国产成人在线播放 | 欧美精品欧美精品系列 | 九九热精品视频在线观看 | 56pao在线 | 亚洲天堂久久新 | 中文字幕成人在线 | 国产精品明星裸体写真集 | 国产午夜精品一区二区三区在线观看 | 一级片av| 久久手机在线视频 | 国产一二区免费视频 | 91免费观看视频 | 天天干夜夜操 | 一区二区三区在线 | 欧 | 中国一级特黄视频 | 中文字幕不卡一区 | 99福利在线观看 | av香蕉 | 欧美日韩亚洲一区二区 | 欧美极品少妇xxxxⅹ免费视频 | 亚洲一区二区不卡在线观看 | 日韩二三区| 999精品网 | 欧美日韩国产一区二区三区 | 精品国产乱码久久久久久影片 | 久久精品久久久久久 | 国产欧美一区二区三区在线看 | 中文字幕一区二区三区精彩视频 | 第一区在线观看免费国语入口 | www.47久久青青 | 精品一二区 | 国产视频精品视频 |