IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> React路由的详解 -> 正文阅读

[JavaScript知识库]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来完成

目前前端路由的主要模式:

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 组件
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:32:00  更:2021-07-31 16:34:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/7 10:50:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码