-
不同的路径渲染不同的组件
-
有两种实现方式
- HashRouter:利用hash实现路由切换
- BrowserRouter:实现h5 Api实现路由的切换
HashRouter
-
利用hash实现路由切换
public\index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#root{
border:1px solid red;
}
</style>
</head>
<body>
<div id="root"></div>
<ul>
<li><a href="#/a">/a</a></li>
<li><a href="#/b">/b</a></li>
</ul>
<script>
window.addEventListener('hashchange',()=>{
console.log(window.location.hash);
let pathname = window.location.hash.slice(1);//把最前面的那个#删除
root.innerHTML = pathname;
});
</script>
</body>
</html>
BrowserRouter
- 利用h5 Api实现路由的切换
history
- HTML5规范给我们提供了一个history接口
- HTML5 History API包括2个方法:
history.pushState()和history.replaceState(),和1个事件window.onpopstate
pushState
-
history.pushState(stateObject, title, url),包括三个参数
- 第一个参数用于存储该url对应的状态对象,该对象可在onpopstate事件中获取,也可在history对象中获取
- 第二个参数是标题,目前浏览器并未实现
- 第三个参数则是设定的url
-
pushState函数向浏览器的历史堆栈压入一个url为设定值的记录,并改变历史堆栈的当前指针至栈顶
replaceState
- 该接口与pushState参数相同,含义也相同
- 唯一的区别在于
replaceState是替换浏览器历史堆栈的当前历史记录为设定的url - 需要注意的是
replaceState不会改动浏览器历史堆栈的当前指针
onpopstate
- 该事件是window的属性
- 该事件会在调用浏览器的前进、后退以及执行
history.forward、history.back、和history.go触发,因为这些操作有一个共性,即修改了历史堆栈的当前指针 - 在不改变document的前提下,一旦当前指针改变则会触发
onpopstate事件
路由的钩子函数
- useHistory,这个钩子可以访问history,可以更好的进行导航
- useLocation, 此钩子可以返回location表示当前URL对象
- useParams, 返回URL参数的键值对的对象
- useRouteMatch 此钩子可以精准匹配路由然后显示对应的页面
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route, Link,
useHistory,
useLocation,
useParams,
useRouteMatch
} from './react-router-dom';
function Home() {
return <div>Home</div>
}
function UserDetail(props) {
console.log('props.match', props.match);
console.log('props.match.params', props.match.params);
// history location match{params}
let params = useParams();//它会用当前组件的路径 进行匹配,不能传参
console.log('params', params);
let history = useHistory();
console.log('history', history);
let location = useLocation();
console.log('location', location);
//这个可以传递路径,想传什么路径就传什么路径
let match = useRouteMatch({ path: '/user/detail/:id', strict: false, sensitive: false });
console.log('useRouteMatch', match);
console.log('useRouteMatch.params', match.params);
return <div>UserDetail</div>
}
ReactDOM.render(
<Router>
<ul>
<li><Link to="/" exact={true}>首页</Link></li>
<li><Link to={{ pathname: '/user/detail/100', state: { id: 100, name: '张三' } }}>用户100详情</Link></li>
</ul>
<Route path="/" exact={true} component={Home} />
<Route path="/user/detail/:id" component={UserDetail} />
</Router>,
document.getElementById('root')
懒加载
- 懒加载返回的必须要是一个promise
const LazyFoo = React.lazy(() => import('./components/Foo'));
function lazy(dynamicImport) {
return function () {
let [Component, setComponent] = React.useState(null);
React.useEffect(() => {
dynamicImport().then(result => {
let LazyComponent = result.default;
setComponent(LazyComponent)
});
}, []);
return Component && <Component />;
}
}
-v6
Switch重命名为Routes
component/render被element替代Routes和Route基于当前位置在React Router中渲染某些内容的主要方法- 您可以把Route考虑为一种类似于if语句的路由,如果其路径与当前URL匹配,则呈现其元素
- Route的caseSensitive属性属性确定是否应以区分大小写的方式进行匹配(默认为false)
function App() {
let [routes, setRoutes] = React.useState(routesConfig);
return (
<div>
{useRoutes(routes)}
</div>
)
}
配置文件routesConfig
const routesConfig = [
{ path: '/', element: <Home />, index: 0 },
{
path: '/user/*',
element: <User />,
index: 1,
children: [
{ path: 'add', element: <UserAdd />, index: 0 },
{ path: 'list', element: <UserList />, index: 1 },
{ path: 'detail/:id', element: <UserDetail />, index: 2 }
]
},
{ path: '/foo', element: <Foo /> }
]
export default routesConfig;
用useNavigate代替useHistory
useNavigate钩子返回一个函数,该函数允许您以编程方式进行导航
function Home() {
let navigate = useNavigate();
function navigateToUser() {
navigate('/user');
};
return (
<div>
<p>Home</p>
<button onClick={navigateToUser}>跳转到/user</button>
</div>
)
}
Redirect 标签删除
- 解决方案:新版的路由需要引入标签
Navigate元素在渲染时更改当前位置
<Router>
<Routes>
<Route path='/login' element={<Login/>}/>
<Route path='/admin' element={<Admin/>}/>
// 重定向到login
<Route path="*" element={<Navigate to="/login" />} />
</Routes>
</Router>