目录
路由
以下讲的都是这个版本: "react-router-dom": "^5.0.2",
(1)简介
React构建的是单页面应用,使用路由实现页面跳转。通过管理 URL,实现组件的切换和状态的变化
react-router: 实现了路由的核心功能,提供了router的核心api。如Router、Route、Switch等,但没有提供有关dom操作进行路由跳转的api;
react-router-dom: 基于react-router,加入了在浏览器运行环境下的一些功能,例如:Link组件,会渲染一个a标签。路由模式分为:BrowserRouter(history)(不带#号)和HashRouter(带#号)。原理--history使用pushState和popstate事件构建路由;hash使用window.location.hash和hashchange事件构建路由。可以通过dom操作触发事件控制路由。
(2)基本使用
-
1、下载
react-route r-dom
库cnpm i react-router-dom --save
-
2、相关组件使用
-
BrowserRouter/HashRouter:
-
是一个路由容器,所有的路由组件(Route)、导航链接(Link)都要放置在该组件内部。
-
import 导入时使用as可以设置一个别名。
-
BrowserRouter没有#,HashRouter有#。
-
-
Switch:路由块,只要匹配到一个地址不往下匹配,相当于for循环里面的break
-
-
3、Route:路由规则,用于匹配路由组件
-
4、exact : Route属性,精确匹配路由
-
5、Link:导航链接,相当于a标签
-
6、使用步骤
import React from 'react';
import {HashRouter as Router, Route} from "react-router-dom";
import IndexPage from "./pages/IndexPage";
import NewsPage from "./pages/NewsPage";
class MyRouter extends React.Component {
render() {
return (
<div>
{/*路由容器,所有的Route 与Link 组件都要放置其内部*/}
<Router>
{/*这里需要一个容器,内部存放多个路由*/}
<div>
{/*方法1:复杂路由放前边,辅助精确匹配*/}
<Route path="/news" component={NewsPage}></Route>
{/*方法2:为根路由添加精确匹配*/}
<Route path="/" exact component={IndexPage}></Route>
</div>
</Router>
</div>
);
}
}
export default MyRouter;
第二步,页面导入 :App.js文件导入使用路由
import React from 'react';
import MyRouter from "../router/router";
class App extends React.Component{
render(){
return (
<div>
{/*使用路由规则*/}
<MyRouter></MyRouter>
</div>
)
}
}
export default App;
第三步,创建链接标签 :IndexPage.js
import {Link} from "react-router-dom";
import MyRouter from "../router/router";
class IndexPage extends React.Component {
render() {
return (
<div>
首页
<Link to="/">首面</Link>
<Link to="/news">新闻页面</Link>
</div>
);
}
}
export default IndexPage;
另一种,组件规则的定义方式,参考官网:https://reactrouter.com/web/guides/quick-start
<Router>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
{/*为根路由添加精确匹配*/}
<Route path="/" exact>
<Home />
</Route>
</Switch>
</div>
</Router>
(3)路由组件懒加载
react-loadable 实现router.js文件路由组件懒加载
cnpm i -S react-loadable
loadable.js:
/*路由懒加载(异步组件)*/
import React from 'react';
import Loadable from 'react-loadable';
//通用的过场组件
const LoadingComponent =(props)=>{
return (
<div>loading...</div>
)
}
//过场组件默认采用通用的,若传入了loading,则采用传入的过场组件
export default (loader,loading = LoadingComponent)=>{
return Loadable({
loader,
loading
});
}
router.js(严格模式下会报出红色警告信息)
import React from "react";
import {BrowserRouter as Router,Switch,Link,Route} from "react-router-dom";
import loadable from "./js/loadable";
// 异步加载组件
const Welcom = loadable(() => import('../pages/Home'))
const UserManage = loadable(() => import('../pages/UserManage'))
const Menus = loadable(() => import('../components/Menu/Menu'))
//……定义/导出 路由规则
(4)路由传参
跳转:声明式导航、编程式导航
不能写a标签,因为a标签的话会刷新整个页面。声明式导航、编程式导航
1.动态路由传参,router.js
<Route path="/news/detail/:id/:title" component={NewsDetailPage}></Route>
在Link 的to 属性中传递,indexPage.js
//传递参数值
<Link to="/news/detail/1/新闻详情页1">新闻详情页1</Link>
//在组件内部获取参数
this.props.match.params.id
以上这种写法有局限性,因为在路由后面我们不确定参数个数或丢失参数时,无法匹配任何组件;需要额外定义一个组件进行提示。
2.编程式跳转传参(导航式跳转)
-
利用导航式路由进行query 传参,注意使用BrowerRouter 模式,防止浏览器缓存
第一步,路由规则定义,router.js
//声明要传递的参数
<Route path="/news/detail" component={NewsDetailPage}></Route>
第二步,通过事件处理函数进行导航,事件处理函数中**this 的指向**,必须为**某个路由对应的组件对象**
<li onClick={()=>{
this.props.history.push({
pathname:"/news/detail",
//search:"?id=1&title=新闻详情2",
query:{
id:1,
title:'新闻详情2'
}
})
}}>新闻详情2</li>
//目标页面获取参数
this.props.location.query.id
this.props.location.search //不会丢失参数,但因为是字符串类型,直接使用不方便
路由传参方式**【总结】**:
1. 动态路由规则定义params 传参:在组件内部使用 this.props.match.params.id 获取参数
2. 导航式路由query 传参:在组件内部使用 this.props.location.query.id 获取参数
(5)嵌套路由
- 在父路由组件中,通过Switch匹配子组件:
<div>
<button onClick={this.returnPage.bind(this)}>返回</button>
商品详情页
<ul>
<li>
<Link to="/goods/item">商品</Link>
</li>
<li>
<Link to="/goods/review">评价</Link>
</li>
<li>
<Link to="/goods/detail">详情</Link>
</li>
<li>
<Link to="/goods/recommend">推荐</Link>
</li>
</ul>
<Switch>
<Route path="/goods/item" component={ItemPage}></Route>
<Route path="/goods/review" component={ReviewPage}></Route>
<Route path="/goods/detail" component={DetailPage}></Route>
<Route path="/goods/recommend" component={RecommendPage}></Route>
</Switch>
</div>
(6)路由认证
模拟路由守卫实现原理,自己制作鉴权认证组件
Redirect组件是一种重定向组件 我们可以利用它来实现路由的分流:
用户访问url=>Redirect分流=>
(1.有权限:去目标路由)
(2.没有权限:重定向去登录路由接口)
router.js
import React from "react"
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Loadable from "../loadable"
import OAuth from "./oAuth.jsx"
class Router extends React.Component {
render() {
return (<BrowserRouter>
<Switch>
<Route path="/home" component={Loadable(() =>import("../views/home/index.js"))}/>
<Route path="/login" component={Loadable(()=>import("../views/login/index.js"))}/>
<Route path="/register" component={Loadable(()=>import("../views/register/index.js"))}/>
<OAuth path="/car" component={Loadable(() => import("../views/car/index.js"))}/>
<OAuth path="/info" component={Loadable(() => import("../views/info/index.js"))}/>
<Route path='/'component={Loadable(() => import("../views/home/index.js"))}/>
</Switch>
</BrowserRouter>)
}
}
export default Router
oAuth.js
import React from "react"
import { Redirect, Switch, Route } from "react-router-dom"
import loadable from "../loadable"
class oAuth extends React.Component {
render() {
console.log(this.props)
let flag = false//假数据 代表是否登录过,真实项目是取缓存
if (!flag) { return <Redirect to="/login"></Redirect> }
else {
return <Route path={this.props.path} component={this.props.component}></Route>
}
}
}
export default oAuth