react-router

路由

前言

传统模式下,我们是把整个应用分成了多个页面,然后通过 URL 进行连接。但是这种每次切换页面都需要重新发送所有请求和渲染整个页面,不止性能上会有影响,同时也会导致整个 JavaScript 重新执行,丢失状态。

安装

npm i -S react-router-dom

SPA

Single Page Application: 单页面应用,整个应用只加载一个页面(入口页面),后续在与用户的交互过程中,通过 DOM 操作在这个单页上动态生成结构和内容

简单说来就是:不管你这个网站有多少页面,我都给你整到一个页面里去。

优点:

  • 有更好的用户体验(减少请求和渲染和页面跳转产生的等待与空白),页面切换快
  • 注重前端,数据和页面内容由异步请求(AJAX)+ DOM 操作来完成,前端处理更多的业务逻辑

缺点:

  • SPA不做页面刷新,只做局部更新,也就是除了你第一次打开网站的时候需要加载整个页面之外,之后的一切站内跳转都是不重载页面的,而是在当前页面进行局部刷新,达到页面切换的效果。因此首次加载页面的时间较长
  • 不利于 SEO

SPA 的页面切换机制

虽然 SPA 的内容都是在一个页面通过 JavaScript 动态处理的,但是还是需要根据需求在不同的情况下分内容展示,如果仅仅只是依靠 JavaScript 内部机制去判断,逻辑会变得过于复杂

通过把 JavaScript 与 URL 进行结合的方式:JavaScript 根据 URL 的变化,来处理不同的逻辑,交互过程中只需要改变 URL 即可。这样把不同 URL 与 JavaScript 对应的逻辑进行关联的方式就是路由,其本质上与后端路由的思想是一样的。

前端路由

前端路由只是改变了 URL 或 URL 中的某一部分,但一定不会直接发送请求,可以认为仅仅只是改变了浏览器地址栏上的 URL 而已,JavaScript 通过各种手段处理这种 URL 的变化,然后通过 DOM 操作动态的改变当前页面的结构

  • URL 的变化不会直接发送 HTTP 请求
  • 业务逻辑由前端 JavaScript 来完成

前端路由:我们知道,在url中,#号之后的内容是不会引起页面跳转的,所以我们利用这一点来实现,当url是#/a的时候,显示a的html片段,同理#/b则显示b的html片段,这样一来,前端就有了自己的路由控制,可以来实现前端自己的 多页面

目前前端路由主要的模式:
  • 基于 URL Hash 的路由
  • 基于 HTML5 History API 的路由

React Router

React Router 提供了多种不同环境下的路由库

  • web
  • native
基于 Web 的 React Router

基于 web 的 React Router 为:react-router-dom

import {Route} from ‘react-router-dom’ //引入路由

组件

BrowserRouter 组件

基于 HTML5 History API 的路由组件

HashRouter 组件

基于 URL Hash 的路由组件

在文件加载的主入口

1.入口文件需要再单独引入

import {BrowserRouter, HashRouter} from ‘react-router-dom’

2.引入进来的router必须包裹着当前项目的所有内容

ReactDOM.render(
  // 引入进来的router必须包裹着当前项目的所有内容
  // <HashRouter> 
  //   <App />
  // </HashRouter>,
  <BrowserRouter> 
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);
Route 组件

通过该组件来设置应用单个路由信息,Route 组件所在的区域就是就是当 URL 与当前 Route 设置的 path 属性匹配的时候,后面 component 将要显示的区域

   <Route  path="/" component={IndexP}></Route>
   <Route  path="/about" component={AboutP}></Route>
   <Route  path="/detail" component={DetailP}></Route>
exact

exact 属性表示路由使用 精确匹配模式,非 exact 模式下 ‘/’ 匹配所有以 ‘/’ 开头的路由

  <Route exact path="/" component={IndexP}></Route>
   <Route exact path="/about" component={AboutP}></Route>
   <Route exact path="/detail" component={DetailP}></Route>
Link 组件

Link 组件用来处理a链接 类似的功能(它会在页面中生成一个a标签),但设置这里需要注意的,react-router-dom 拦截了实际 a标签的默认动作,然后根据所有使用的路由模式(Hash 或者 HTML5)来进行处理,改变了 URL,但不会发生请求,同时根据 Route 中的设置把对应的组件显示在指定的位置

  • Link组件 只改变URL
  • path属性:匹配URL
<Link to = "/">首页</Link><span>|</span>
<Link to = "/about">关于我们</Link><span>|</span>
<Link to = "/detail">详情</Link><span>|</span>
to 属性

to 属性类似 a 标签中的 href

传递 props

<Route exact path='/' component={Home}

如果 Route 使用的是 component 来指定组件,那么不能使用 props

Route : render传递参数

在父组件传递参数

 function App() {
     let [use,setUse] =useState ("给indexP传参")
 	 return (
  		  <div className="App">		
				 <Route exact path="/" render={()=>{
				          //给IndexP子组件传递参数
				          return <IndexP use={use} setUse={setUse}></IndexP>
				 }}></Route>
		 </div>
  );
}

export default App;

通过 render 属性来指定渲染函数,render 属性值是一个函数,当路由匹配的时候指定该函数进行渲染

在子组件接收参数

import React from 'react'

export default function IndexP(props){
    console.log(props)
    // props.setUse("在子组件使用方法")

    let {use,setUse} = props;

    return <h2>
                <a onClick={()=>{
                    setUse("在子组件使用方法")
                }}>首页</a>
           </h2>
}
NavLink 组件

NavLink 与 Link 类似,但是它提供了两个特殊属性用来处理页面导航
NavLink也需要 exact属性进行精确匹配模式

定义组件

import React from "react"
// import {Link} from 'react-router-dom'
import {NavLink} from 'react-router-dom'

export default function Nav(){
    return (<nav>
                <NavLink
                        exact
                        to = "/"
                        activeClassName = "active"
                        activeStyle = {{
                                color:"red"
                        }}
                >首页</NavLink>                                
                {/* <Link to = "/">首页</Link><span>|</span>
                <Link to = "/about">关于我们</Link><span>|</span>
                <Link to = "/detail">详情</Link><span>|</span> */}
           </nav>)
}

在需要的地方引入文件

import Nav from './component/nav'
function App() {
  return (
    <div className="App">       
       <Nav></Nav>       
    </div>
  );
}

export default App;
activeStyle

当当前 URL 与 NavLink 中的 to 匹配的时候,激活 activeStyle 中的样式

activeClassName

与 activeStyle 类似,但是激活的是 className

isActive

默认情况下,匹配的是 URL 与 to 的设置,通过 isActive 可以自定义激活逻辑,isActive 是一个函数,返回布尔值

Switch 组件

该组件只会渲染首个被匹配的组件
相当于:
switch(表达式) {
case n:
代码块
break;
case n:
代码块
break;
default:
默认代码块
}
案例内容:判断路由的路径,显示相对应的一个页面,没有与之相对应的页面则显示提示页面

import {Route,Switch, Redirect} from 'react-router-dom' //引入路由
<Switch>    
         <Route exact path="/" render={()=>{
              return <Redirect to="/list/1"></Redirect>
          }}></Route>     
          <Route exact path="/list/:page" render={(props)=>{
              return <IndexP {...props}></IndexP>
          }}></Route>
          
          <Error component={Error}></Error>
</Switch>
Redirect 组件

重定向

to

设置跳转的 URL

动态路由

为了能给处理上面的动态路由地址的访问,我们需要为 Route 组件配置特殊的 path

withRouter 组件(高阶组件,高阶函数,高阶路由)

如果一个组件不是路由绑定组件,那么该组件的 props 中是没有路由相关对象的,虽然我们可以通过传参的方式传入,但是如果结构复杂,这样做会特别的繁琐。幸好,我们可以通过 withRouter 方法来注入路由对象

import React from 'react'
import {withRouter} from 'react-router-dom'
// console.log(withRouter) 
 function DetailP(props){
    console.log(props)
    return <div>
               <h1>详情</h1> 
               <button onClick={()=>{
                   console.log(props)
               }}>按钮</button>
           </div>
}

export default withRouter(DetailP)

hooks Router5.0之后出现的

不在类组件内使用
  • useHistory :获取history对象
  • useLocation :获取Location对象
  • useParams :获取Params对象
  • useRouteMatch :获取Match对象
import {useHistory ,useLocation , useParams,useRouteMatch } from "react-router-dom"
export default function IndexP(){
    console.log(useHistory ())
    console.log(useLocation ())
    console.log(useParams())
	console.log(useRouteMatch())
    return <div>
              首页
           </div>
}

路由参数

  • history : 历史记录以及路由给我们的一些操作
    -history.go(-1)
    - goBack 返回上一步
    - goForward 前进一步
    - push:修改当前的url
    - replace:修改当前的URL
import React from 'react'

export default function IndexP(props){
    console.log(props)
    let {history} = props
    console.log(history.length)
    return <div>
               <h1>首页 </h1> 
               <button onClick={()=>{                    
                    history.push("/about","state跳转路由传递的参数")  //会增加历史记录,能够返回上一步
                    // history.replace("/about") //不会增加历史记录,不能够返回上一
               }}>按钮</button> 
           </div>
}       
  • location :获取当前的 URL的一些信息
    - pathname:当前的URL
    - search:参数
    - state:跳转路由时,传递的参数
  • match:当前路由匹配的相关规则
    - params:动态路由传过来的参数
react-router其优点可以总结如下:
  • 风格: 与React融为一体,专为react量身打造,编码风格与react保持一致,例如路由的配置可以通过component来实现

  • 简单: 不需要手工维护路由state,使代码变得简单

  • 强大: 强大的路由管理机制,体现在如下方面

    1. 路由配置: 可以通过组件、配置对象来进行路由的配置

    2. 路由切换: 可以通过 Redirect进行路由的切换

    3. 路由加载: 可以同步记载,也可以异步加载,这样就可以实现按需加载

    4. 使用方式: 不仅可以在浏览器端的使用,而且可以在服务器端的使用

当然react-router的缺点就是API不太稳定,在升级版本的时候需要进行代码变动。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值