配置路由表及登录态校验

前几天我完成了一个哔哩哔哩的博主视频下的一个react项目,借此项目来巩固学习的知识,这篇文章主要记录我在该项目用到的路由知识

配置路由表

在src下新建一个router文件夹,在router文件夹下新建index.jsrouter.js

router.js是将将项目中的所有路由引入并制作成一张路由表,在该文件下可以进行组件路由路径配置、组件路由名称配置、组件路由携带属性配置、路由的懒加载配置和路由缓存配置等。

具体配置代码:

//  router.js文件
import { lazy } from "react";
import Home from '../views/Home'
import { withKeepAlive } from 'keepalive-react-component';
const routes = [
    {
        path: '/',
        name: 'home',
        //  使用"keepalive-react-component"插件实现该页面缓存,即在跳转到其他页面后再次返回不会重新刷新页面,保持原有的滚动位置和数据
        component: withKeepAlive(Home, { cacheId: 'home', srcoll: true }),
        //  设置组件携带title
        meta: {
            title: '知乎日报-WebApp'
        }
    },
    {
        //  params形式路由传参,需要在路由表中提前留好参数位置
        path: '/detail/:id',
        name: 'name',
        component: withKeepAlive(lazy(() => import('../views/Detail')), { cacheId: 'detail', srcoll: true }),
        meta: {
            title: '新闻详情-知乎日报'
        }
    },
    {
        path: '/personal',
        name: 'personal',
        //  使用 lazy 实现路由懒加载
        component: lazy(() => import('../views/Personal')),
        meta: {
            title: '个人中心-知乎日报'
        }
    },
    // 剩下的配置大同小异,不在展示··········
];
//  暴露路由表
export default routes;

index.js文件是路由的真正配置文件,将router.js文件中导出的路由表使用map动态生成Route路由

//  router.js文件
export default function RouterView() {
    return (
        <Suspense fallback={<Mask visible={true}><DotLoading color="white" /></Mask>}>
            <Routes>
                {routers.map(item => {
                    let { name, path } = item;
                    return <Route key={name} path={path} element={<Element {...item} />} />;
                })}
            </Routes>
        </Suspense>
    )
};
  • Suspense 是用在路由懒加载中,当路由页面没有渲染出来时,渲染fallback的返回值,fallback中的一般都是一个加载中的动画,用于减少白屏和过渡,提升体验,在这里我使用的是 antd-mobile 插件带的加载效果 Mask,可以自行去官网学习如何使用
  • router6 使用关键字 Routes 包在 Route 外,取代了原先5时的 Switch
  • 使用 map 循环生成 Route,key关键字是一定需要的,在所有使用到 map 生成的元素都必须要保证 key 值的唯一性
  • element=<Element {...item} />是将路由信息传递给自己包装的 Element 组件,可以在 Element 组件中进行一些操作,比如传值,修改页面标题和登录态校验
//  Element组件+登录态校验
//  假定 checkList 中的路径是需要进行登录态校验的,该方法用于判断是否需要进行登录态校验操作
const isCheckLogin = (path) => {
    //  从redux中获取登录信息,base中存放了登录信息
    let { base: { info } } = store.getState(),
        checkList = ['/personal', '/store', '/update'];
    return !info && checkList.includes(path);
}

const Element = function Element(props) {
    //  接收{...item}中传过来的值,这些值其实都是路由表中对象的键值对信息(routes.js中配置的键值对信息),component是要作为组件的,所以需要重命名成首字母大写
    let { component: Component, meta, path } = props;
    //  调用函数,判断是否需要进行登录态校验,同时控制渲染的是组件还是 loading 效果
    let isShow = !isCheckLogin(path);
    //  用来更新函数组件
    let [_, setRandom] = useState(0);
    // 登录态校验 每次状态改变都需要判断是否需要登录态校验,否则只会在初始化时进行登录态校验
    useEffect(() => {
        if (isShow) return;
        // 如果info不存在,跳转的地址是三个中的一个,从服务器异步获取登录者信息,info存放的是登陆者的信息
        // 在此处用立即执行函数包 async,如果将 async 写在函数 function 处,将会返回一个 Promise 对象,该组件是用作渲染其他组件的,返回值必须为 jsx 不能为Promise
        (async () => {
            //  调用redux中的函数,从给定的接口中获取登录信息
            let infoAction = await actions.base.queryUserInfoAsync();
            let info = infoAction.info;
            if (!info) {
                // 获取后还是不存在,那么就是没有登陆,进行提示登录
                Toast.show({
                    icon: 'fail',
                    content: '请先登录'
                })
                // 跳转到登录页,replace 是在登陆组件时需要用到的,其实就是登录界面的返回前一个界面的功能问题
                navigate({
                    pathname: '/login',
                    search: `?to=${path}`
                }, { replace: true })
                return;
            }
            // 获取了信息,说明是登陆状态,派发任务把信息存储到容器中
            store.dispatch(infoAction);
            // 每次获取完登录信息后都需要更新组件,更新info,从而正确完成登录态校验
            setRandom(+new Date());
        })();
    });
    //修改页面的TITLE
    let { title = "知乎日报-WebApp" } = meta || {};
    document.title = title;
    //获取路由信息,基于属性传递给组件
    const navigate = useNavigate(),
        location = useLocation(),
        params = useParams(),
        [usp] = useSearchParams();
    return (
        <>
            {
                isShow ? <Component
                    navigate={navigate}
                    location={location}
                    params={params}
                    usp={usp} /> :
                    <Mask visible={true}>
                        <DotLoading color="white" />
                    </Mask>
            }
        </>
    )
};

最后,路由配置完需要在 App 中包裹上相应的插件,例如:BrowserRouter,KeepAliveProvider

import React from "react";
import { BrowserRouter } from 'react-router-dom';
import RouterView from "./router";
import { KeepAliveProvider } from "keepalive-react-component/lib";
const App = function App() {
    return (
        <BrowserRouter>
            <KeepAliveProvider>
                <RouterView />
            </KeepAliveProvider >
        </BrowserRouter>
    )
}
export default App;
posted @ 2023-04-12 20:22  超重了  阅读(104)  评论(0编辑  收藏  举报