react路由学习 react-router-dom初始化

 下载

pnpm add react-router-dom

 路由基本设置

1.配置路由表

react-router-domv6版本 可以跟vue一样配置路由表

创建文件夹router/index.tsx

import React from 'react'
import { createBrowserRouter } from 'react-router-dom'
import { Router } from '@remix-run/router' // 导入Router类型
import Home from '@/view/home'
import Login from '@/view/login'
// 创建路由
const router: Router = createBrowserRouter([
  {
    path: '/',
    element: <Home /> //注册组件的第一种方式
  },
  {
    path: '/login',
    element: React.createElement(Login) // 注册组件的第二种方式
  }
])

export default router

2.main.ts 

初始

import ReactDOM from 'react-dom/client'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')!).render(<App />)

修改后 

import ReactDOM from 'react-dom/client'
import { RouterProvider } from 'react-router-dom'
import router from '@/router/index'
// 可以删除app.tsx 直接拿路由组件替换
ReactDOM.createRoot(document.getElementById('root')!).render(<RouterProvider router={router}></RouterProvider>)

完成

 

也可以不删除App.tsx

在App.tsx中

import { RouterProvider } from 'react-router-dom'
import router from './router'
export default function App() {
  return <RouterProvider router={router}></RouterProvider>
}

效果是一样的

路由跳转的几种方式

1.使用NavLink组件

import React from 'react'
import { NavLink } from 'react-router-dom'

export default function login() {
  return (
    <div>
      login组件<NavLink to='/'>跳转home</NavLink>
    </div>
  )
}
import React from 'react'
import { NavLink } from 'react-router-dom'
export default function home() {
  return (
    <div>
      home组件:<NavLink to='/login'>跳转login</NavLink>
    </div>
  )
}

 

点击跳转home

成功跳转

2.使用link组件

和navlink一样 两者之间的区别是 navlink可以判断激活状态可以设置样式 link就是普通的a标签

import React from 'react'
import { Link } from 'react-router-dom'
export default function login() {
  return (
    <div>
      login组件<Link to='/'>跳转home</Link>
    </div>
  )
}

3.使用Navigate组件 重定向

 我们可以随便设置一个路由来展示作用

import React from 'react'
import { createBrowserRouter, Navigate } from 'react-router-dom'
import { Router } from '@remix-run/router' // 导入Router类型
import Home from '@/view/home'
import Login from '@/view/login'
// 创建路由
const router: Router = createBrowserRouter([
  {
    path: '/',
    element: <Home />
  },
  {
    path: '/login',
    element: React.createElement(Login)
  },
  {
    path: '/aaa',
    element: <Navigate to='/login'></Navigate>
  }
])

export default router

定义了一个/aaa的路由 访问之后让他重定向到login页面

 

访问aaa重定向到了login

 

 

4.使用编程路由导航 useNavigate

import React from 'react'
import { useNavigate } from 'react-router-dom'
export default function login() {
  // 初始化路由
  const $router = useNavigate()
  // 点击跳转
  const btn = () => {
    $router('/')
  }
  return (
    <div>
      <p>login组件</p>
      {/* 设置一个按钮 */}
      <button onClick={btn}>点击跳转主页</button>
    </div>
  )
}

 

点击跳转成功

404页面

追加一条路由规则在路由表最下面 * 表示全部 上面路由表匹配不到 会最后走到404

{
    path: '*',
    element: <div>404!!! 当前页面不存在</div>
}

访问/666 

 

嵌套路由

1.创建子路由

 {
    path: '/',
    element: <Home />,
    children: [
      {
        path: 'child',
        element: <Child />
      }
    ]
  },

这个意思代表我们创建了一个子路由 子路由命名方式只写名称会自动拼接父路径

比如父级goods路由下面新增一个child 你可以写 child 或者是/goods/child 不能写/child 

2.父组件设置二级路由出口

使用Outlet组件 Outlet相当于Vue中的routerview组件    

import { Link, Outlet } from 'react-router-dom'
export default function home() {
  return (
    <div>
      home组件:<Link to='/login'>跳转login</Link>
      {/* 二级路由出口 */}
      <Outlet />
    </div>
  )
}

动态路由传参

新增动态路由

:参数名称进行动态传递

 {
    path: '/goods/:goodsId/order/:orderId',
    element: <Goods />
  },

 组件通过useParams进行获取

import { useParams } from 'react-router-dom'
export default function goods() {
  const params = useParams()
  return (
    <div>
      <h3>商品Id:{params.goodsId}</h3>
      <h3>订单Id:{params.orderId}</h3>
    </div>
  )
}

手动输入访问

 

 loader

这个东西有点类似于vue-router中的路由独享守卫 在路由中配置loader函数 路由加载之前调用

{
    path: '/goods/:goodsId/order/:orderId',
    element: <Goods />,
    // loader
    loader: ctx => {
      console.log(ctx)
      return {}
    }
  },

浏览器打印 可以看到这个loader是在页面render之前触发的  

 

在loader也可以拿到params参数 但是这样做意义不大

loader返回一个对象  在页面可以通过useLoaderData钩子拿到

{
    path: '/goods/:goodsId/order/:orderId',
    element: <Goods />,
    // loader
    loader: ctx => {
      console.log(ctx)
      return {
        a: 1
      }
    }
  },
const LoaderData = useLoaderData()
console.log(LoaderData)

 

举例1

在vue中我们可以使用独享守卫来进行接口的请求 拿到对应页面的数据 loader也可以发送异步请求

{
    path: '/goods/:goodsId/order/:orderId',
    element: <Goods />,
    // loader
    loader: async ctx => {
      let res: { code: number; msg: string } = await new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve({
            code: 200,
            msg: '请求成功'
          })
        }, 1000)
      })
      return {
        ...res
      }
    }
  },

 

其实这样用的也比较少

举例2

 当我们在做权限拦截的时候可以通过loader来进行判断

{
    path: '/goods/:goodsId/order/:orderId',
    element: <Goods />,
    // loader
    loader: async ctx => {
      // 模拟一个token
      let token = '10086'
      // 判断没有登录去login
      if (!token) return edirect('/login')
      return {
        username: 'admin',
        token
      }
    }
  },

 

我们再把token改为空字符串 

{
    path: '/goods/:goodsId/order/:orderId',
    element: <Goods />,
    // loader
    loader: async ctx => {
      // 模拟一个token
      let token = ''
      // 判断没有登录去login
      if (!token) return edirect('/login')
      return {
        username: 'admin',
        token
      }
    }
  },

访问goods 返回login

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值