React——路由——概念、环境、创建路由、页面跳转、传参数、配置符 *、子路由、重定向、React解决跨域

目录

1、概念:

2、环境

(1)下载第三方模块

(a)ts开发情况下,

(b)js开发情况下,

(2)引入

3 创建路由

4 页面跳转-Link和useNavigate

5 路由使用注意事项

6 传参数

 1 )通过url传参数

2 )动态传参数

 3 )state传参数

7 配置符 *

8 子路由 / 理由嵌套

1 )子路由配置

2 )主路由与子路由相互跳转

9 重定向

1 )重定向基础

方式1:在 Route 的 element 中使用

方式2 : 在组件的返回值中使用

2 )路径错误默认显示页面

10 路由首守-登陆判断

11 React解决跨域

1)直接在 package.json 中添加 proxy 属性

2)安装 http-proxy-middleware :

3)npm run eject 


1、概念:

从版本的React-Router5.x开始,路由彻底改变了,和以后的版本完全不兼容。所以要注意版本。

对当页面应用模式提供多页面效果

Link和useNavigate实现组件切换时,实计上伴随着组件的销毁与创建,所以建议只有整体页面切换时才使用路由,而局部切换时使用最原始的隐藏显示为佳,这样可以保让组件中通过ajax得到的数据一直存在。同样的道理,子路由的使用也需要特别小心。

2、环境

(1)下载第三方模块

(a)ts开发情况下,

下载模块"react-router-dom"和 "@types/react-router-dom"

npm i --save react-router-dom @types/react-router-dom

(b)js开发情况下,

只需下载模块"react-router-dom"

(2)引入

BrowserRouter 与history模式类似,HashRouter与hash模式类似

BrowserRouter和HashRouter两者的区别,和vue中history和hash的区别一样,面试回答vue中的就可以了

BrowserRouter和HashRouter只能二选一,而且这两个标签只用一次,子路由中也不要使用(如果用了不会报错,但是会很奇怪),一个网站只用一次

BrowserRouter太长,常常使用别名Router,as是给BrowserRouter换一个变量名

import {  
	  BrowserRouter as Router, //BrowserRouter太长,常常使用别名Router,Router:是自己取的名字,是一个类型别名
	  Route, 
      Routes, //专门注册网址的,
      Link,
      useNavigate,
      useParams,
      useLocation,
      Navigate
} from 'react-router-dom';

3 创建路由

<BrowserRouter>
				<Routes>
					<Route path='/main' element={<Main />} />
					<Route path='/one' element={<One />} />
					<Route path='/two' element={<Two />} />
				</Routes>
</BrowserRouter>
		 
<BrowserRouter>
  		  {/*Nav这个自定义组件与路由出来的界面同时显示, 页面跳转-Link和useNavigate可以在该组件中控制*/}
  			<Nav />
				<Routes>
					<Route path='/main' element={<Main />} />
					<Route path='/one' element={<One />} />
					<Route path='/two' element={<Two />} />
				</Routes>
</BrowserRouter>

4 页面跳转-Link和useNavigate

Link相当于超连接

useNavigate是hook

import {Link, useNavigate} from 'react-router-dom';

Line标签
<Link to={
   
   {pathname:'/one'}}>one</Link>

或ts代码-useNavigate
let navigate = useNavigate();
function toTwo() {
		navigate({pathname:'/one'});
        navigate('/one'});
}

5 路由使用注意事项

Link和useNavigate实现组件切换时,实计上伴随着组件的销毁与创建,

所以建议只有整体页面切换时才使用路由,

而局部切换时使用最原始的隐藏显示为佳,

这样可以保让组件中通过ajax得到的数据一直存在。

同样的道理,子路由的使用也需要特别小心

6 传参数

三种方式:

1、通过url传参数(有种类型:Link, useNavigate)、

2、动态传参数、

3、state(参数不会显示在页面上),更常用

 1 )通过url传参数

传:import {Link, useNavigate} from 'react-router-dom';

接收:import {useLocation} from 'react-router-dom';

url的组成:

协议       //ip:port/pathname search hash

search   ?querystring

querystring  key=value&key2=value2

hash      #/home/car?dat=123

//传参 方式一:Link to
传参:
<Link to='/one?name=泪王'>传参</Link>
<Link to={
   
   {pathname:"home",search:"goods=123"}}>传参</Link>

//传参 方式二:useNavigate
let navigate = useNavigate();
function to() {
		navigate({pathname:"home",search:"goods=123"});
}

接收1:
import {useLocation} from 'react-router-dom';
	let location = useLocation();
	let search = location.search;
	search = decodeURI(search);//转码   decodeURI浏览器自带的函数,有中文就可以使用这个函数进行转码
	console.log(search);//   /one?name=泪王
接收2:自己封装,将query解成对象
import {useLocation} from 'react-router-dom';
  let location=useLocation()
  let obj=location.search.queryobj()
  String.prototype.queryobj=function (){
    let obj={}
    this.split("?"[i].split("&").map(el=>{
      let arr=el.split("=")
      obj[arr[0]]=arr[1]
    }))
    return obj
  }

2 )动态传参数

<Route path='/two/:name/:sex' element={<Two />} />
name和sex 是变量名,可以随便写,只要前面是/two,就可以匹配到/two页面
也就是/:name/:sex随便写(但是必须写),都可以加载同一个组件

用法:根据自己后面传的动态参数,给页面加载不同的内容

第一步设置可传参数

设置可传参数
<Route path='/two/:name/:sex' element={<Two />} />

第二步传参数

传参
navigate({pathname:`/two/小王/女`});
navigate("/two/小王/女");
或
<Link to={
   
   {pathname:`/two/小王/女`}}>two</Link>
<Link to="/two/小王/女">two</Link>

第三步使用hook-useParams函数接收参数

接收参数 (在跳转到的页面中)
import {Link, useParams} from 'react-router-dom';
let person = useParams();
console.log(person.name,person.sex)  //小王 女

 3 )state传参数

state的参数不会在页面上显示

使用场景:比如token码,一些隐蔽的参数

search和state可以同时使用

//传递参数关键代码
import {useNavigate} from 'react-router-dom';
let navigate = useNavigate();
//1、
navigate({pathname:'/one'},{state:{id:1,sex:'女',name:'小五'}});
//2、
navigate({pathname:'/one',search:"?page=10"},{state:{id:1,sex:'女',name:'小五'}});
//3、
<Link to={
   
   {pathname:'/one'}},state:{
   
   {id:1,sex:'女',name:'小五'}}>two</Link>

接收参数使用hook-useLocation函数,接收到的对象state是一个Object类型,

所以必须类型断言才能取出属性值

//接收参数关键代码
import {useLocation} from 'react-router-dom';

const location = useLocation();
let stu = location.state as {id:number,sex:string,name:string};

 vue3.0中跳转传参也有 state

7 配置符 *

<Route path="/*" element={<组件1 />}></Route>
<Route path="/test" element={<组件2 />}></Route>
{/*
  /test匹配到组件2
  /teacher匹配到组件1
*/}

8 子路由 / 理由嵌套

父路由已经注册 import {BrowserRouter } from 'react-router-dom',并且使用了<BrowserRouter></BrowserRouter>,在子组件和其它任何组件都不用再引入和在使用了

BrowserRouter和HashRouter只能二选一,而且这两个标签只用一次,子路由中也不要使用(如果用了不会报错,但是会很奇怪),一个网站只用一次

1 )子路由配置

方式1:

第1步 在配置 主路由 的path属性后面 加 "/*" ,eg:  path="/one/*"

//router.jsx
<BrowserRouter>
			<Routes>
                  <Route path="/" element={<Main />}></Route>
                  <Route path="/one/*" element={<One />}></Route>
			</Routes>
</BrowserRouter>

第2步:在主路由对应的组件中使用配置新的路由, 子路由的访问path为 "主路由+子路由"

/one              匹配到<Person />  
/one/stu        匹配到组件<Stu />
/one/aabb     匹配不到组件

//One.jsx
<Routes>  //因为父组件写了<BrowserRouter></BrowserRouter>,所以其它的组件就不写了
			<Route  path="/" element={<Person />} />
            //stu是相对于当前的网址,不用加父组件的One了
			<Route  path="/stu" element={<Stu />} />
            //下面这种写法是错的,匹配不到。  //
            <Route  path="/One/boss" element={<Boss />} />
</Routes>

方式2:

 router.jsx

<Route path="/test" element={<Test />}>
        <Route path="/a" element={<Testa />}>
        </Route  >
</Route  >

src/views/test/Index.jsx

import React, { useState } from 'react'
import {Outlet} from "react-router-dom"
export default function Index() {
  return (
    <div>
      <Outlet></Outlet>
    </div>
  )
}

 src/views/test/testa.jsx

import React, { useState } from 'react'
export default function Index() {
  return (
    <div>
     <p>testa</p>
    </div>
  )
}

2 )主路由与子路由相互跳转

  • 不管是主路由还是子路由,都可以在浏览器中输入正确的地址访问到;

  • 不管是主路由还是子路由,只要组件内嵌在标签"BrowserRouter"中,就可以使用hook-useNavigate或标签Link直接使用正确的路由path访问到;

9 重定向

1 )重定向基础

方式1:在 Route 的 element 中使用

重定向需使用到组件Navigate   ==>   import {Navigate} from 'react-router-dom';

Route中的element不设置组件,而设置别的已经设置好的Route的path, 显示效果就是该path对应的组件。

子路由可以重定向到主路由,主路由中也可以重定向到子路由。

			<Routes>
				<Route path="/" element={<Main />}></Route>
				<Route path="/one/*" element={<One />}></Route>
				<Route path="/two" element={<Two />}></Route>
				<Route path="/three" element={<Three />}></Route>
				<Route path="/*" element={<Page404 />}></Route>
				{/* 主路由重定向到主路由:  重定向到path:/two对应的组件<Two />中, 网址会显示为/two */}
				<Route path="/b" element={<Navigate to="/two" />} />
				{/* 主路由重定向到子路由:   定向到path:/one/stu对应的组件XXX中,网址会显示为/one/stu */}
				<Route path="/a" element={<Navigate to="/one/stu" />} />
 		</Routes>

方式2 : 在组件的返回值中使用

<Route path="/a" element={<Index/>} />

import React from 'react';
import {Navigate} from 'react-router-dom';

export default function Index(flag:string) {
	if(flag=="stu") {
		 	return <Navigate to="/one" replace={true} />
	}else {
			return <Navigate to="/two" replace={true} />
	}
}

2 )路径错误默认显示页面

主路由中使用 /* 来匹配,子路由中重定向到主路由中的 /*

//App.tsx 第一级路由(主路由)
<Route path="/" element={<Main />}></Route>
<Route path="/one/*" element={<One />}></Route>
<Route path="/two" element={<Two />}></Route>
<Route path="/three" element={<Three />}></Route>
<Route path="/*" element={<Page404 />}></Route>

    <Page404 />是路由错误的默认访问网页
    localhost:3000--<Main>
    localhost:3000/one--<One>
    localhost:3000/two--<Two>
    localhost:3000/three---<Three>
    localhost:3000/aabb---<Page404>

//One.tsx 第二级路由(子路由)
<Routes>
  <Route  path="/boss" element={<Boss />} />
  <Route  path="/*" element={<Navigate to="/404" />} />
</Routes>

localhost:3000/one/boss--<Boss>
localhost:3000/one/aabb--重定向到localhost:3000/404--匹配主路由的/*---找到<Page404 />
<Navigate to="/404" />中的"/404"是任意写的一个不存在的路由path,所以不是非要写成"/404"

10 路由首守-登陆判断

方法1:

写一个带插槽的组件,在该组件中统一判断是否登陆,进而决定该组件中插入的组件是否正常加入。

在路由配置组件时,所有组件使用插槽组件包裹。

 src/router/index.jsx

import React,{useState} from 'react';
import {BrowserRouter,Link, Routes, Route, Navigate} from 'react-router-dom';
import Main from './Main';
import Login from '../views/Login';
import Goods from '../views/Goods';
import About from './About';
import RouterFilter from './RouterFilter';
function Index() {
	const[islogin, setIslogin] = useState<boolean>(false);
	return (
		<BrowserRouter>
				<Routes>
					<Route path="/" element={<RouterFilter><Main /></RouterFilter>}></Route>
					<Route path="/goods" element={<RouterFilter><Goods /></RouterFilter>}></Route>
					<Route path="/about" element={<RouterFilter><About /></RouterFilter>}></Route>
					<Route path="/login" element={<Login />}></Route>
				</Routes>
		</BrowserRouter>
	);
}
export default Index;

 src/router/RouterFilter.jsx

import React,{useContext} from 'react'
import MyContext from './MyContext';
import {Navigate} from 'react-router-dom';

function RouterFilter({children}:any) {
	if(已经登陆) {
		return children;
	}else {//未登陆
		return <Navigate to="/login" replace={true} />
	}
}
export default RouterFilter;

方法2:

通过属性传值的方式,进行判断

src/router/index.jsx

import React from 'react'
import {BrowserRouter,Routes,Route} from "react-router-dom"
import OAuth from "./oAuth"
import Home from "../views/home"
import Login from "../views/login"
import Register from "../views/register"
import User from "../views/user"
import Car from "../views/car"
import Root from "../views/root"
export default function Router() {
  return (
    <BrowserRouter>
      <Routes>
         <Route path='/' element={<Home/>}></Route>
         <Route path='/home' element={<Home/>}></Route>
         <Route path='/login' element={<Login/>}></Route>
         <Route path='/register' element={<Register/>}></Route>
         <Route path='/user' element={<OAuth Component={User}/>}></Route>
         <Route path='/car' element={<OAuth Component={Car}/>}></Route>
         <Route path='/root' element={<OAuth Component={Root}/>}></Route>
      </Routes>
     </BrowserRouter>
  )
}

src/router/oAuth.jsx

import React from 'react'
import {Navigate} from "react-router-dom"
export default function OAuth({Component}) {
    console.log(Component)
    let token=window.localStorage.getItem("token")
    if(token){
        return (<Component></Component> )
    }
    else{
        return <Navigate to="/login"></Navigate>  
    }
}

11 React解决跨域

1)直接在 package.json 中添加 proxy 属性

只适用于只有一个后台服务器,后端不用写cors了

在前端的 package.json文件中:

"proxy":"http://localhost:7001/"

2)安装 http-proxy-middleware :

适用于多个后台服务器

安装 http-proxy-middleware :

npm install http-proxy-middleware
或者
yarn add http-proxy-middleware

这里注意,http-proxy-middleware 模块是有版本区别的,默认安装最新版本,然后在 src 目录下新建 setupProxy.js :

const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
    app.use(
        "/api",
        createProxyMiddleware({
            target: "http://localhost:3000", // 后台服务地址以及端口号
            changeOrigin: true, // 是否开启代理
            pathRewrite: {
                "/api": "", // 代理名称
            },
        })
    );
};

重新 npm run start 即可解决跨域

3)npm run eject 

已经进行了 npm run eject ,就直接修改 config>webpackDevServer.config.js :

module.exports = function (proxy, allowedHost) {
  const disableFirewall =
    !proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true';
 
  // 配置proxy对象解决跨域
  proxy = {
    ...proxy,
    '/api': {
      target: 'http://localhost:3000', // 后台服务地址以及端口号
      changeOrigin: true, //是否跨域
      pathRewrite: { '^/api': '/' },// 代理名称
      secure: false
    },
  }
 
  return { 
    ......
    }

猜你喜欢

转载自blog.csdn.net/qq_52301431/article/details/127382312
今日推荐