React路由的详解
Posted ZZZ --- jh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React路由的详解相关的知识,希望对你有一定的参考价值。
React路由
路由
当应用变得复杂时, 就需要分块进行处理和展示, 传统模式下, 我们是把整个应用分成了多个页面, 然后通过URL进行连接. 但是这种方式也有一些问题, 每次切换页面都需要重新发送所有请求和渲染整个页面, 不止性能上会有影响, 同时也会导致整个javascript重新执行,丢失状态.
SPA
概念
单页面应用, Single Page Application , 整个应用只加载一个页面(入口页面), 后续在与用户的交互过程中, 通过DOM操作在这个单页面上动态生成结构和内容.
优点
- 有更好的用户体验(减少请求和渲染和页面跳转产生的等待与空白), 页面切换快
- 重前端, 数据和页面内容由异步请求(ajax)+DOM操作来完成, 前端处理更多的业务逻辑
缺点
- 首次进入处理慢
- 不利于SEO(搜索引擎优化)
SPA的页面切换机制
虽然SPA的内容都是在一个页面通过JavaScript动态处理的, 但是还是需要根据需求在不同的情况下分内容展示, 如果仅仅只是依靠JavaScript内部机制去判断, 逻辑会变得过于复杂, 通过JavaScript与URL进行结合的方式: JavaScript根据URL的变化来处理不同的逻辑, 交互过程中只需要改变URL即可. 这样把不同URL与JavaScript对应的逻辑进行关联的方式就是路由, 其本质上与后端路由的思想是一致的.
前端路由
前端路由只是改变URL或URL中的某一部分, 但一定不会直接发送请求, 可以认为仅仅只是改变了浏览器地址栏上的URL而已, JavaScript通过各种手段处理这种URL的变化, 然后通过DOM操作动态的改变当前页面的结构
- URL的变化不会直接发送HTTP请求
- 业务逻辑由前端JavaScript来完成
目前前端路由的主要模式:
-
基于URL Hash 的路由
-
基于html5 History API的路由
网址: https://developer.mozilla.org/zh-CN/docs/Web/API/History_API
React Router
网址: https://reacttraining.com/react-router/
React Router 提供了多种不同环境下的路由库
- web
- native
基于Web的React Router
基于 web 的 React Router 为:react-router-dom
安装
npm i -S react-router-dom
组件
url的hash
-
URL的hash就是锚点,本质上是改变window.location的href属性;
-
我们可以直接赋值location.hash来改变href,但是页面不发生刷新
-
<html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <a href="#view1">视图1</a> <a href="#view2">视图2</a> <a href="#view3">视图3</a> <div id="view"></div> <script> function getHash() console.log(window.location.hash); view.innerHTML = window.location.hash; getHash(); window.addEventListener('hashchange',getHash) </script> </body> </html>
以上这个案例点哪个按钮页面就会显示出来对应的锚点,控制台也会输出对应的
路由的类型: BrowserRouter 组件和HashRouter 组件,他俩得包裹着所有的内容
BrowserRouter 组件
基于 HTML5 History API 的路由组件
引入: import BrowserRouter from "react-router-dom";
HashRouter 组件
基于 URL Hash 的路由组件
引入: import HashRouter from "react-router-dom";
Route组件
通过该组件来设置应用单个路由信息, Route组件所在的区域就是当URL与当前Route设置的path属性匹配的时候, 后面component将要显示的区域.
path属性
匹配url;( 匹配url的方式不是相等, 而是以给定的url开头)
component属性
当url和前面的path匹配上的时候,compinent里面写显示的内容
exact属性
exact属性表示路由使用精确匹配模式, 非exact模式下’/’ 匹配所有以’/’ 开头的路由.
<!-- src/view/index.js -->
import React from "react";
export default function IndexPage()
return <h1>首页</h1>
<!-- src/view/about.js -->
import React from "react";
export default function AboutPage()
return <h1>关于我们</h1>
<!-- src/view/aboutMore.js -->
import React from "react";
export default function AboutMorePage()
return <h1>详情</h1>
<!-- src/index.js -->
import React from 'react';
import ReactDOM from 'react-dom';
// import HashRouter from "react-router-dom";
import BrowserRouter from "react-router-dom";
import './index.css';
import App from './App';
ReactDOM.render(
<BrowserRouter >
<App />
</BrowserRouter>,
document.getElementById('root')
);
<!-- src/app.js -->
import React from 'react';
import Route from "react-router-dom";
import IndexPage from "./view/index";
import AboutPage from "./view/about";
import AboutMorePage from "./view/aboutMore";
function App()
return (
<div className="App">
<Route path='/' exact component=IndexPage />
<Route path='/about' exact component=AboutPage />
<Route path='/about/more' exact component=AboutMorePage />
</div>
);
export default App;
Link组件
Link组件用来处理a链接
类似的功能(它会在页面中生成一个a标签), 但设置这里需要注意的, react-router-dom拦截了实际a标签的默认动作, 然后根据所有使用的路由模式(Hash或者HTML5)来进行处理, 改变了URL, 但不会发生请求, 同时根据Route中的设置把对应的组件显示在指定的位置.
作用:
只改变url
to属性
to属性类似a标签中的href
<!-- src/component/nav.js -->
import React from 'react';
import Link from "react-router-dom";
export default function Nav()
return(
<nav>
<Link to='/'>首页</Link>
<span> | </span>
<Link to='/about'>关于我们</Link>
<span> | </span>
<Link to='/about/more'>详情</Link>
<span> | </span>
</nav>
)
<!-- src/app.js -->
import React from 'react';
import Route from "react-router-dom";
import IndexPage from "./view/index";
import AboutPage from "./view/about";
import AboutMorePage from "./view/aboutMore";
import Nav from "./component/nav";
// path中: 匹配url的方式不是相等, 而是以给定的url开头
function App()
return (
<div className="App">
/* link组件 只改变url */
<Nav />
/* path属性: 匹配url */
<Route path='/' exact component=IndexPage />
<Route path='/about' exact component=AboutPage />
<Route path='/about/more' exact component=AboutMorePage />
</div>
);
export default App;
传递props
如果 Route 使用的是 component 来指定组件,那么不能使用 props
render属性: 通过 render 属性来指定渲染函数,render 属性值是一个函数,当路由匹配的时候指定该函数进行渲染
import React, useState from 'react';
let [user,setUser] = useState('router');
<Route path='/' exact render=()=>
return <IndexPage user=user setUser=setUser/>
/>
<!--src/view/index.js-->
import React from "react";
export default function IndexPage(props)
console.log(props);
let user,setUser = props;
return <h1>
<a onClick=()=>
setUser('React可不')
>啦啦</a>
首页
</h1>
动态路由
为了能给处理上面的动态路由地址的访问, 需要为Route组件配置特殊的path.
目的: 就是为了给不同的组件传递不同的参数
路由参数:
-
history: 历史记录以及路由给我们的一些操作
goBack 返回上一步
goForward 前进一步
push: 修改当前的url
replace: 修改当前的url
// history.push(’/about’); //这个的回退功能是可以用的. 会增加历史记录
// history.replace(’/about’); //这个没有回退一说. 不会增加历史记录
-
location: 获取当前url的一些信息
- pathname – 当前的URL
- search – 接口参数
- state – 跳转路由时传递的参数
-
match: 当前路由匹配的相关规则
- params – 动态路由传过来的参数
<!-- src/view/index.js -->
import React from "react";
import NavLink, Link from "react-router-dom";
export default function IndexPage()
return (
<div>
<h1>留言列表</h1>
<Link to='/list/1'>1</Link>
<span> | </span>
<Link to='/list/2'>2</Link>
<span> | </span>
<Link to='/list/3'>3</Link>
<span> | </span>
<Link to='/list/4'>4</Link>
<span> | </span>
<Link to='/list/5'>5</Link>
<span> | </span>
<Link to='/list/6'>6</Link>
</div>
)
<!-- app.js -->
import React from 'react';
import Route,Switch from "react-router-dom";
import IndexPage from "./view/index";
import Page404 from "./view/Page404";
function App()
return (
<div className="App">
<Switch>
<Route path='/list/:page' exact render=(props)=>
return <IndexPage ...props ></IndexPage>
></Route>
<Page404 component=Page404></Page404>
</Switch>
</div>
);
export default App;
以上的这个案例注意path路径写成动态的
NavLink组件
NavLink 与 Link类似, 但是它提供了两个特殊属性用来处理页面导航.
activeStyle
当当前URL 与 NavLink 中的to匹配时, 激活activeStyle中的样式
activeClassName
与 activeStyle 类似, 但是激活的是 className
<!-- src/component/nav.js -->
import React from 'react';
import NavLink from "react-router-dom";
export default function Nav()
return(
<nav>
<NavLink
to='/'
exact
activeClassName='active'
activeStyle=
color:'red'
>首页</NavLink>
<span> | </span>
<NavLink
to='/about'
exact
activeClassName='active about'
activeStyle=
color:'red'
>关于我们</NavLink>
<span> | </span>
<NavLink
to='/about/more'
exact
activeClassName='active about more'
activeStyle=
color:'red'
>详情</NavLink>
<span> | </span>
</nav>
)
isActive
默认情况下, 匹配的是URL 与 to的设置, 通过 isActive 可以自定义激活逻辑, isActive是一个函数, 返回布尔值
Switch组件
该组件只会渲染首个被匹配的组件
<!-- app.js -->
import React from 'react';
import Route,Switch from "react-router-dom";
import IndexPage from "./view/index";
import AboutPage from "./view/about";
import Page404 from "./view/Page404";
function App()
return (
<div className="App">
<Switch>
<Route path='/' exact component=IndexPage></Route>
<Route path='/about' exact component=AboutPage></Route>
<Page404 component=Page404></Page404>
</Switch>
</div>
);
export default App;
以上这个案例中要注意Page404写的顺序,如果写在Switch里面的最上面的话,不管加载哪个页面都只会出现页面飞走的内容,所以他要写在Switch里面的最下面.
Redirect组件
to属性: 设置跳转的URL
<!-- app.js -->
import React from 'react';
import Route, Switch, Redirect from "react-router-dom";
import IndexPage from "./view/index";
import Page404 from "./view/Page404";
function App()
return (
<div className="App">
<Switch>
<Route path='/' exact render=()=>
return <Redirect to='/list/1'></Redirect>
></Route>
<Route path='/list/:page' exact render=(props)=>
return <IndexPage ...props ></IndexPage>
></Route>
<Page404 component=Page404></Page404>
</Switch>
</div>
);
export default App;
以上这个案例目的就是让页面加载出来的时候就在page=1的页面中,并且让上面的地址栏里面显示的也是这个http://localhost:3000/list/1
withRouter组件(高阶组件, 高阶函数,高阶路由)
如果一个组件不是路由绑定组件,那么该组件的 props 中是没有路由相关对象的,虽然可以通过传参的方式传入,但是如果结构复杂,这样做会特别繁琐。所以就可以通过 withRouter 方法来注入路由对象
<!-- src/view/about.js -->
import React from "react";
import Inner from "./inner";
export default function AboutMorePage(props)
let location,match = props;
// console.log(match);
return (
<div>
<h1>关于我们</h1>
<Inner />
</div>
)
<!-- src/view/inner.js -->
import React from "react";
import withRouter from "react-router-dom";
function Inner(props)
return (
<div>
<h1>Inner</h1>
<button onClick=()=>
console.log(props);
>按钮</button>
</div>
)
export default withRouter(Inner);
hooks (Router5.0之后出现的)
- 不在类组件内使用
- useHistory : 获取History对象
- useLocation : 获取Location对象
- useParams : 获取Params
- useRouteMatch : 获取Match
总结:
- 路由有它的优点也有它的缺点
- React Router 提供了web环境和native环境的路由库
- 路由的类型: BrowserRouter 组件和HashRouter 组件
以上是关于React路由的详解的主要内容,如果未能解决你的问题,请参考以下文章