React 系列之基础三
React 路由
React 路由帮组我们根据浏览器地址栏的 URL 将应用划分到不同的视图.
1. React-router
1. 快速开始
npm install --save react-router-dom
使用简单示例:
import {
BrowserRouter as Router,
Switch, Route, Link
} from "react-router-dom"
const App = () => {
const padding = {
padding: 5
}
return (
<Router>
<div>
<Link style={padding} to="/">home</Link>
<Link style={padding} to="/notes">notes</Link>
<Link style={padding} to="/users">users</Link>
</div>
<Switch>
<Route path="/notes">
<Notes />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
<div>
<i>Note app, Department of Computer Science 2020</i>
</div>
</Router>
)
}
- BrowserRouter 是一个 Router
它使用 HTML5 的 history API(pushState, replaceState 和 popState 事件) 保持UI 与 URL 同步.
通常地址栏 URL 变化, 浏览器会加载一个新的页面. 然而, 借助 HTML history Api BrowserRouter, 我们可以使用浏览器 URL 在 react-application 中进行内部"路由". 因此这种方式, URL 变化, 页面的内容是通过 JavaScript 来替换的.
- Link
在路由内部, 定义 Link 组件, 用于修改地址栏 URL - Switch & Route
基于浏览器 URL 渲染的组件是在组件 Route 下定义的
并通过 Switch 保证要基于 url 渲染的 Route
2. 参数化路由 (useParams)
在 上面 Link 组件中, to 的值是固定的. 同样, 也可以设置参数化路由值.
<Route path="/notes/:id">
<Note notes={notes} />
</Route>
在这个 Route 中, 通过 冒号 :id 标签参数来定义路由的 path. 下面是Note.js 定义, 里面通过 useParams 获取 url 参数:
import {
useParams
} from 'react-router-dom'
const Note = ( { notes } ) => {
// 通过 useParams 获取 url 的参数
const id = useParams().id
const note = notes.find(n => n.id === Number(id))
return ...
}
3. useHistory 使用
有了这个 函数, 组件就可以访问一个 history 对象. 历史记录对象可以用于编程化地修改浏览器的 url.
例如在 一个 Login 组件中:
import {
// ...
useHistory
} from 'react-router-dom'
const Login = (props) => {
const history = useHistory()
// 登录提交 处理函数
const onSubmit = (event) => {
event.preventDefault()
// 当前登录的用户 mluukkai
props.onLogin('mluukkai')
// 修改浏览器 url
history.push('/')
}
return (
<div>
<h2>login</h2>
<form onSubmit={onSubmit}>
<div>
username: <input />
</div>
<div>
password: <input type='password' />
</div>
<button type="submit">login</button>
</form>
</div>
)
}
4. 重定向 (redirect)
<Redirect to="xx" />
假设需求: 如果用户未登录, 跳转到登录页面, 如果已经登录则正常跳转
<Route path="/users" render={() =>
user ? <Users /> : <Redirect to="/login" />
} />
5. 参数化路由的缺陷 (useRouteMatch)
在参数化路由中:
<Route path="/notes/:id">
<Note notes={notes} />
</Route>
Note 组件需要传递到 note 集合, 根据 useParams 给到的 id 查询出 需要显示的 note 实例.
一种方法是使用 react-router 的 useRouteMatch
- 在定义应用路由部分的组件中不可能使用useRouteMatch-hook。 让我们把路由组件的使用从 App 中移除
- 组件变成如下所示:
import {
// ...
useRouteMatch
} from "react-router-dom"
const App = () => {
// ...
const match = useRouteMatch('/notes/:id')
const note = match
? notes.find(note => note.id === Number(match.params.id))
: null
return (
<div>
<div>
<Link style={padding} to="/">home</Link>
// ...
</div>
<Switch>
<Route path="/notes/:id">
<Note note={note} />
</Route>
<Route path="/notes">
<Notes notes={notes} />
</Route>
// ...
</Switch>
<div>
<em>Note app, Department of Computer Science 2020</em>
</div>
</div>
)
}
每当渲染组件时, url 变化 都会执行如下命令:
const match = useRouteMatch(’/notes/:id’)
它匹配到 url 的 id, 用于 找到显示的 便笺
const note = match
? notes.find(note => note.id === Number(match.params.id))
: null
版权声明:本文为JIANG_RZJ原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。