-
Notifications
You must be signed in to change notification settings - Fork 0
8. react router
对于 web 应用来说,有一个导航条是很常见的,它可以切换应用的视图
在老派的web应用中,更改应用显示的页面将由浏览器向服务器发出 HTTP GET 请求并显示表示返回视图的 HTML 来完成。
在单页应用中,我们实际上总是在同一页上。 浏览器运行的 Javascript 代码会产生不同“页面”的错觉。 如果 HTTP 请求是在切换视图时发出的,那么它们只用于获取 JSON 格式的数据,新视图可能需要这些数据才能显示出来。
import React, { useState } from 'react'
const Home = () => (
<div> <h2>TKTL notes app</h2> </div>
)
const Notes = () => (
<div> <h2>Notes</h2> </div>
)
const Users = () => (
<div> <h2>Users</h2> </div>
)
const App = () => {
const [page, setPage] = useState('home')
const toPage = (page) => (event) => {
event.preventDefault()
setPage(page)
}
const content = () => {
if (page === 'home') {
return <Home />
} else if (page === 'notes') {
return <Notes />
} else if (page === 'users') {
return <Users />
}
}
const padding = {
padding: 5
}
return (
<div>
<div>
<a href="" onClick={toPage('home')} style={padding}>
home
</a>
<a href="" onClick={toPage('notes')} style={padding}>
notes
</a>
<a href="" onClick={toPage('users')} style={padding}>
users
</a>
</div>
{content()}
</div>
)
}
每个视图都作为自己的组件实现。 我们将视图组件信息存储在名为page 的应用状态中。 这个信息告诉我们,表示视图的哪个组件应该显示在菜单栏下面。
缺点:
- 地址保持不变
- 无法回退
- 应用变得庞大之后,这套逻辑维护起来也异常麻烦
- 无法添加书签
...
所以需要一套路由来管理
2.1 简单使用效果
2.2 实际上讨论的是BrowserRouter ,因为这里的导入是通过重命名导入的对象实现的
import {
BrowserRouter as Router, //重命名
Switch, Route, Link
} from "react-router-dom"
BrowserRouter 是一个 Router,它使用 HTML5的history API (pushState、 replaceState 和 popState 事件)保持 UI 与 URL 同步。
通常,当地址栏中的 URL 发生更改时,浏览器会加载一个新页面。 然而,借助于HTML5 history APIBrowserRouter,可以使用浏览器地址栏中的 URL 在 React-application 中进行内部“路由”。 因此,即使地址栏中的 URL 发生了变化,页面的内容也可以通过 Javascript 来操作,浏览器也不会从服务器加载新的内容。 使用后退和前进操作,以及制作书签,仍然像在传统网页上一样合乎逻辑。
2.3 History介绍
history
是一个独立的第三方js库,可以用来兼容在不同浏览器、不同环境下对历史记录的管理,拥有统一的API
。具体来说里面的history
分为三类
-
老浏览器的
history
: 主要通过hash
来实现,对应createHashHistory
-
高版本浏览器: 通过
html5
里面的history
,对应createBrowserHistory
-
node
环境下: 主要存储在memeory
里面,对应createMemoryHistory
// 内部的抽象实现
function createHistory(options={}) {
...
return {
listenBefore, // 内部的hook机制,可以在location发生变化前执行某些行为,AOP的实现
listen, // location发生改变时触发回调
transitionTo, // 执行location的改变
push, // 改变location
replace,
go,
goBack,
goForward,
createKey, // 创建location的key,用于唯一标示该location,是随机生成的
createPath,
createHref,
createLocation, // 创建location
}
}
- 执行URL前进
- 检测URL回退
本质就是监听 URL
的变化,然后匹配路由规则,显示相应的页面,并且无须刷新。目前单页面使用的路由就只有两种实现方式
-
hash
模式 -
history
模式
2.4 react-router 原理
实现URL
与UI
界面的同步。其中在react-router
中,URL
对应Location
对象,而UI
是由react components
来决定的,这样就转变成location
与components
之间的同步问题
react-router
在history
库的基础上,实现了URL
与UI
的同步,分为两个层次来描述具体的实现。
在react-router
中最主要的component
是Router RouterContext Link
,history
库起到了中间桥梁的作用
-
browserHistory
进行路由state
管理,主要通过sessionStorage
//保存 路由state(router state) {route: '/about'}
function saveState(key, state) {
...
window.sessionStorage.setItem(createKey(key), JSON.stringify(state));
}
//读取路由state
function readState(key) {
...
json = window.sessionStorage.getItem(createKey(key));
return JSON.parse(json);
}
进行路由匹配,最终渲染对应的组件
3.1 安装
-
react-router
React Router 核心 -
react-router-dom
用于 DOM 绑定的 React Router -
react-router-native
用于 React Native 的 React Router -
react-router-redux
React Router 和 Redux 的集成 -
react-router-config
静态路由配置的小助手
后者比前者多出了 <Link>
<BrowserRouter>
这样的 DOM 类组件,安装后者就可以了
npm install --save react-router-dom
3.2 基本用法
- BrowserRouter
- HashRouter
Router
组件的history
属性,用来监听浏览器地址栏的变化,并将URL解析成一个地址对象,供 React Router 匹配。
history
属性,一共可以设置三种值。
-
browserHistory: 用于支持HTML5历史API的现代Web浏览器
-
hashHistory: 用于希望将位置存储在当前URL的哈希中以避免在页面重新加载时将其发送到服务器的情况
-
createMemoryHistory: 用作引用实现,也可用于非DOM环境,如对本地或测试的反应(测试代码中可能会用到)
每个history对象都有以下属性:
- history.length - 历史堆栈中的条目数
- history.location - 当前的 location
- history.action - 当前导航操作
history.push(path, [state])
history.replace(path, [state])
history.go(n)
history.goBack()
history.goForward()
history.canGo(n) (only in createMemoryHistory)
3.2.1 使用BrowserRouter
BrowserRouter 是一个 Router,它使用 HTML5的history API (pushState、 replaceState 和 popState 事件)保持 UI 与 URL 同步。
-
简单使用
-
参数化
-
重新定向