前言
早期多個頁面藉助a標籤實現路由的跳轉,也就是多頁面編程,n個導航對應n個html.而且點擊鏈接後,整個頁面會刷新,頁面會跳轉-如果需據會發送請求獲取數據。react是單頁面多組件應用,鏈接稱為路由鏈接,點擊後,會全局更新,也就是局部刷新,並且不會像發送請求,這裏是説這個請求並不是因為你點擊鏈接產生的,組件中的數據還是需要請求的。而點擊產生的路徑與渲染組件的對應關係取決於react-router插件庫了。
SPA
- 單頁Web應用(single page web application,SPA)。
- 整個應用只有一個完整的頁面。
- 點擊頁面中的鏈接不會刷新頁面,只會做頁面的**局部更新。
-
數據都需要通過ajax請求獲取, 並在前端異步展現。
1. 路由的理解
1. 什麼是路由?
- 一個路由就是一個映射關係(key:value)
- key為路徑, value可能是function或component
2. 路由分類
-
後端路由:
- 理解: value是function, 用來處理客户端提交的請求。
- 註冊路由: router.get(path, function(req, res))
/* 請求地址: http://localhost:3000/search/users?q=aa 後台路由 key: /search/users value: function () {} */ app.get("/search/users", function (req, res) { const {q} = req.query axios({ url: 'https://api.github.com/search/users', params: {q} }).then(response => { res.json(response.data) }) })- 工作過程:當node接收到一個請求時, 根據請求路徑找到匹配的路由, 調用路由中的函數來處理請求, 返回響應數據
-
前端路由:瀏覽器端路由
- 理解: value是component,用於展示頁面內容
-
註冊路由:
<Route path="/test" component={Test}> - 工作過程:當瀏覽器的path變為/test時(路由鏈接可以直接修改瀏覽器地址), 當前路由組件就會變為Test組件
3. 路由工作原理
、
這是典型的多頁面應用,點擊導航區切換,請求另一個頁面,展示區是變了。會跳轉到另一個頁面,並且會刷新,多個展示區需要多個html。
原理:
- 一開始的地址欄是沒有參數的,127.0.0.1/ ,沒有多頁面應用的xxx.html的後綴(.html 代表一個頁面o)
- 點擊路由鏈接後,路由會修改瀏覽器的地址,127.0.0.1/ home/ 頁面並不會發生跳轉。【區別於a鏈接 點擊後不跳轉】
- 路由中檢測瀏覽器的路徑(參數)變化(這裏是會忽略前面的ip 以及port)匹配組件參數,展示相應的組件
路由監測的實現: 得益於history對象 瀏覽器歷史記錄
點擊導航區,路徑改變 === 路徑改變,被檢測 === 匹配組件,展示區變化。
-
為什麼點擊路由鏈接後地址欄會變路徑呢?誰監測路徑的變化呢?
依靠瀏覽器的歷史記錄 history對象
我們一般不會直接去操作這個window.history 去操作瀏覽器的路徑 歷史記錄的修改以及替換 因為原生的api不好用 so
藉助一個庫history.js 這個創建的history對象本質也是操作了bom的history
history.push/forward/go/back/replace
兩種路由模式: history: hash(# 兼容性好) browser
2. react-router-dom的理解
- react-router 插件庫其實有三種實現 適用於三種平台 web(dom) native(原生) anywhere(通用性強 api 過多)
- react的一個插件庫。本質是react寫的,依賴於react才可以工作。
- 專門用來實現一個SPA應用
- 基於react的項目基本都會用到此庫。
router: 路由器 管理路由
route: 路由(接口 天線)
原生寫react
1.複雜需要多個html 引入各種react文件 編碼慢
2.通過js修改為jsx的形式依靠瀏覽器babel 翻譯 代碼過多瀏覽器忙不過來
3. 使用cli 簡單快速搭建react 應用 cli是webpeck 搭建的,他有好多loader plugins 由很多功能‘
4.安裝腳手架 create-react-app庫幫助你安裝cli
5.創建項目 create-react-app 項目名
6.啓動 npm start
webpeck 官方把關於react的配置文件隱藏了 執行eject 會暴露處所有的配置文件並且回不去了
7.react中不建議使用jquery 因為他注重的是操作原生dom。而 react是不關注視圖層的
axios: 輕量 可運行在服務端 支持promise 本質就是xmlHttpRequest對象的封裝
3. react-router-dom相關API
3.1. 內置組件
-
<BrowserRouter>
路由器 管理路由 一個應用只有一個路由器。
<BrowserRouter> <App/> </BrowserRouter><HashRouter>
- 路由器 管理路由。
-
<Route>
作用:註冊路由 匹配組件 path 路徑 components 組件
<Route path="/about" component={About}/>
-
<Redirect>
1.一般寫在所有路由註冊的最下方,當所有路由都無法匹配時,跳轉到Redirect指定的路由 2.具體編碼: <Switch> <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Redirect to="/about"/> </Switch> Redirect是值得匹配不到後,顯示的組件,就是最後承擔者,兜底的人。 -
<Link>
路由鏈接link 本質是a標籤 作用就是點擊後修改地址欄路徑 瀏覽器的歷史記錄就會工作 當路徑變化就會匹配組件 <a href="./home.html">Home</a> ===> <Link to="/home">Home</Link> 使用方式與a鏈接一樣,只是href的值是具體的網頁地址,to的屬性值是路徑參數(沒有點) Link需要被路由器所管理,這個路由器需要具體,hash / browser,link 可以實現瀏覽器的路徑變化以及歷史記錄的添加 -
<NavLink>
點擊時路由鏈接高亮的效果,點擊時給鏈接動態的追加一個類class=active 由於boot裏面active恰好是高亮 可設置 activeClassName 屬性 制定選中後的類名 注意boot裏面樣式權重大,因為boot默認會給點擊的添加active類,導致你有兩個類。??可是為什麼閃爍你寫的需要important組件標籤體就是標籤的children屬性 值可通過this.prop.children獲取
-
<Switch>
<MyNavLink to="/about">About</MyNavLink> <MyNavLink to="/home">Home</MyNavLink> /* 制定瀏覽器路徑以及瀏覽器的歷史記錄 */ <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Route path="/home" component={Test}/> /* 匹配路徑 顯示組件 會發現都展示了 如果註冊的路由特別多,他會一直匹配,只要滿足就顯示,效率低下 */1. 通常情況下,path和component是一一對應的關係。 2. Switch可以提高路由匹配效率(單一匹配) 匹配一個後不會繼續匹配了。
3.2. 其它
- history對象
- match對象
- withRouter函數
4. 路由使用
1.明確好界面中的導航區、展示區
2.導航區的a標籤改為Link標籤
<Link to="/xxxxx">Demo</Link>
3.展示區寫Route標籤進行路徑的匹配
<Route path='/xxxx' component={Demo}/>
4.<App>的最外側包裹了一個<BrowserRouter>或<HashRouter>
4.1 路由組件與一般組件
1.寫法不同:
一般組件:<Demo/>
路由組件:<Route path="/demo" component={Demo}/>
2.存放位置不同:
一般組件:components
路由組件:pages
3.接收到的props不同:
一般組件:寫組件標籤時傳遞了什麼,就能收到什麼
路由組件:接收到三個固定的屬性
history:
go: ƒ go(n)
goBack: ƒ goBack()
goForward: ƒ goForward()
listen:f listen(listenr)
push: ƒ push(path, state)
replace: ƒ replace(path, state)
location: history.location === location
location:
pathname: "/about"
search: ""
state: undefined
match:
isExact: true 是否精準匹配
params: {}
path: "/about"
url: "/about"
4.2 樣式丟失
1.public/index.html 中 引入樣式時不寫 ./ 寫 / (常用)
2.public/index.html 中 引入樣式時不寫 ./ 寫 %PUBLIC_URL% (常用)
3.使用HashRouter
4.3 路由的嚴格匹配與模糊匹配
<MyNavLink to="/home/a/b">Home</MyNavLink>
<Route path="/home" component={Home}/>
拿出 home a b 與home可以匹配 給的多是可以的
1.默認使用的是模糊匹配(簡單記:【輸入的路徑】必須包含要【匹配的路徑】,且順序要一致)
2.開啓嚴格匹配:<Route exact={true} path="/about" component={About}/>
3.嚴格匹配不要隨便開啓,需要再開,有些時候開啓會導致無法繼續匹配二級路由
4.4 開啓repalce模式
<Link repalce to="/xxxxx">Demo</Link> 替換模式
4.5 withRouter
export default withRouter(Header)
Header組件的props裏就有history了
withRouter可以加工一般組件,讓一般組件具備路由組件所特有的API
withRouter的返回值是一個新組件
5. 嵌套路由使用
1.註冊子路由時要寫上父路由的path值
2.路由的匹配是按照註冊路由的順序進行的
6. 向路由組件傳遞參數數據
1.params參數
路由鏈接(攜帶參數):<Link to='/demo/test/tom/18'}>詳情</Link>
註冊路由(聲明接收):<Route path="/demo/test/:name/:age" component={Test}/>
接收參數:this.props.match.params
2.search參數
路由鏈接(攜帶參數):<Link to='/demo/test?name=tom&age=18'}>詳情</Link>
註冊路由(無需聲明,正常註冊即可):<Route path="/demo/test" component={Test}/>
接收參數:this.props.location.search
備註:獲取到的search是urlencoded編碼字符串,需要藉助querystring解析
3.state參數
路由鏈接(攜帶參數):<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>詳情</Link>
註冊路由(無需聲明,正常註冊即可):<Route path="/demo/test" component={Test}/>
接收參數:this.props.location.state
備註:刷新也可以保留住參數
7. 多種路由跳轉方式
藉助this.prosp.history對象上的API對操作路由跳轉、前進、後退
-this.prosp.history.push()
-this.prosp.history.replace()
-this.prosp.history.goBack()
-this.prosp.history.goForward()
-this.prosp.history.go()
8. BrowserRouter與HashRouter的區別
1.底層原理不一樣:
BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
HashRouter使用的是URL的哈希值。
2.path表現形式不一樣
BrowserRouter的路徑中沒有#,例如:localhost:3000/demo/test
HashRouter的路徑包含#,例如:localhost:3000/#/demo/test
3.刷新後對路由state參數的影響
(1).BrowserRouter沒有任何影響,因為state保存在history對象中。
(2).HashRouter刷新後會導致路由state參數的丟失!!!
4.備註:HashRouter可以用於解決一些路徑錯誤相關的問題。