儘管寫過 outlet 路由的配置。 考慮到 token 判定和 路由頁 變更,我不瞭解v6是不是有更詳解的做法。 決定調一下配置,期望 在任何頁面非同步更新時,token 都可以在跳轉前 被檢測到,防止無 token 跳轉發生。 補上404頁面( 地址欄 頁面不存在時,展示404頁面 ) ![](h ...
儘管寫過 outlet 路由的配置。
考慮到 token 判定和 路由頁 變更,我不瞭解v6是不是有更詳解的做法。
決定調一下配置,期望 在任何頁面非同步更新時,token 都可以在跳轉前 被檢測到,防止無 token 跳轉發生。
補上404頁面( 地址欄 頁面不存在時,展示404頁面 )
為 src 文件配置 v6版本:路由子組件
App.js
import { HashRouter, Routes, Route } from 'react-router-dom';
import Main from './main';
import Login from './page/login'
import Home from './page/home/home'
import About from './page/about/about'
import Integrated from './page/integrated/integrated'
import Sidebar from './page/sidebar/sidebar'
import Latent from './page/latent/latent'
import Particulars from './page/particulars/particulars'
import SecurityCheck from './page/securityCheck/securityCheck'
import FourPage from './compoment/404';
function App() {
{/* 預設顯示頁面將不需要填寫路徑 ,子路由不需要寫/斜杠跳轉時會帶有*/ }
return (
<HashRouter>
<Routes>
{/* Main 負責token的判定(刷新和前往) */}
<Route path='/' element={<Main />} >
<Route path='/login' element={<Login />} ></Route>
<Route path='/about' element={<About />} >
<Route path='' element={<Integrated />} ></Route>
<Route path='sidebar' element={<Sidebar />} >
<Route path='' element={<Latent />} ></Route>
<Route path='particulars' element={<Particulars />} ></Route>
<Route path='securityCheck' element={<SecurityCheck />} ></Route>
</Route>
</Route>
<Route path='/home' element={<Home />} ></Route>
</Route>
{/* 頁面重定向,當跳轉的頁面不存在時,前往404~ */}
<Route path='*' element={<FourPage />}></Route>
</Routes>
</HashRouter>
);
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
創建和 App.js 、index.js 同級別的 main.js
// main 組件, 充當 路由子組件的主體
// 判定 page頁發生改變
// 判定 token 的 狀態變更
import React, { Component, useEffect, useState } from 'react'
import { Outlet, useLocation, useNavigate } from 'react-router-dom';
import storage from './util/storage';
const Main = () => {
const location = useLocation(); //獲取生命周期鉤子(頁面變化)
const navigate = useNavigate(); //獲取生命周期鉤子(page跳轉)
const Token = storage.get('token'); //獲取本地緩存:token
const [newToken, oldToken] = React.useState()
useEffect(() => { //監聽location變化
if (!Token) { //不存在
if (location.pathname === '/') { //地址欄不全
navigate('/login')
}
else if (location.pathname != '/login') {//地址為登錄後
navigate('/login')
}
} else { //存在
if (location.pathname === '/') { //地址欄不全
navigate('/login')
}
}
oldToken(Token)
}, [location,Token])
return <Outlet context={[newToken, oldToken]}></Outlet>
}
export default Main
在src中,創建 util 配置文件夾
配置 storage.js
var storage = {
set(key, value) { // 添加/編輯 緩存
localStorage.setItem(key, JSON.stringify(value))
},
get(key) { // 取出緩存數據
return JSON.parse(localStorage.getItem(key))
},
remover(key) { // 移除指定緩存
localStorage.removeItem(key)
}
}
export default storage;
為page文件創建
login.js 組件
import React, { Component } from 'react'
import storage from '../../util/storage'
import { useNavigate, useOutletContext } from 'react-router-dom';
const Login = () => {
const [newToken, oldToken] = useOutletContext();
const navigate = useNavigate();
let params = {
message: '這是跳轉時攜帶的參數',
}
const storageToken = () => {
if (!newToken) {
storage.set('token', '這是被存儲的token')
navigate('/about', { state: params });
} else {
storage.remover('token')
}
oldToken(() => { return storage.get('token')})
}
const Btn = () => {
if (!newToken) {
return <>
<button onClick={storageToken}>點擊緩存token</button>
</>
} else {
return <>
<button onClick={storageToken}>點擊清除token</button>
</>
}
}
return <>
<h4>這裡是登錄前</h4>
<Btn />
<br />
<span>{newToken}</span>
</>
}
export default Login
about.js 組件
import React from 'react';
import storage from '../../util/storage'
import { Outlet, useNavigate, useLocation, useOutletContext } from 'react-router-dom';
export default function About() {
const navigate = useNavigate();
const [newToken, oldToken] = useOutletContext();
// 需要註意的是 useNavigate() 跳轉只能在無狀態組件中進行
let ddd = ['c', 'n']
const [count, setCount] = React.useState(ddd); // 數據共用
// 需要註意的是,它只能傳入兩組欄位,一組為原始數據,一組變更數據,用作對比時,每次數據變動
// 頁面隨之更新 傳入的數據類型由自己決定
const state = useLocation() //接收參數
console.log('state', state)
// navigate('', {}) // 前往預設頁
// navigate('/home', {}) // 前往其他頁
// navigate('文件名/子文件', {}) //前往子級
// navigate('文件名', {replace: true}) //前往當前路由其他同級頁 replace: true 重定向
return (
<>
<h4>About</h4>
<button onClick={() => {
navigate('test', { state: ddd });
// state 傳參不限制傳參類型
}}>點擊Test頁</button>
<button onClick={() => {
storage.remover('token');
setTimeout(() => {
oldToken(storage.get('token'))
}, 500)
}} >在頁內清token</button>
<Outlet context={[count, setCount]} />
<div>{newToken}</div>
</>
)
}