🥳React路由学习,实现动态路由

108 阅读1分钟

动态路由

第一想法是用lazy(() => import('./pages/page1/index.tsx')) 但是import参数不支持变量,只能是写死的路径。

import() 的路径必须是静态字符串,因为构建工具需要在构建阶段解析模块路径

vite的import.meta.glob方法动态导入组件

image.png

 const modules = import.meta.glob("./pages/*.jsx");
 console.log(modules);

image.png

动态拼接route

接口获取权限

export const getAdminMenus = () => {
  return new Promise((resolve) => {
    window.setTimeout(() => {
      resolve([
        {
          name: 'page1',
          route: '/page1',
          filePath: '/page1/index.tsx',
        },
      ]);
    }, 1000);
  });
};

整理import.meta.glob

const components = Object.keys(modules).reduce((prev, cur) => {
  prev[cur.replace('./pages', '')] = modules[cur];
  return prev;
}, {}) ;
//components:{/page1/index.tsx : import("/src/pages/page1/index.tsx")}

useEffect处理用户权限

  useEffect(() => {
    getAdminMenus().then((adminMenus: any) => {
      setMenus(adminMenus);
      setLoading(false);
      // 获取菜单后动态添加路由
      router.routes[0].children = adminMenus.map((menu: any) => ({
        path: menu.route,
        Component: lazy(components[menu.filePath])
      }));
    })
  }, []);

route简单使用

初始化

npm create vite 
pnpm i react-router-dom

使用

createBrowserRouter传入数组对象组件

RouterProvider组件传入数组

import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import Page1 from './pages/page1'
const router = createBrowserRouter([{
  path: '/page1',
  Component: Page1,
}])
function App() {
  return (
    <RouterProvider router={router} />
  )
}
export default App

重定向

const router = createBrowserRouter([{
  path: '/page1',
  Component: Page1,
},{
  path: '/',
  element: <Navigate to="/page1" />,
}])

自定义404页面

const router = createBrowserRouter([{
  path: '/page1',
  Component: Page1,
},{
  path: *,
 Component: NotFound,
}])

Link与Outlet

Outlet 是一个占位符组件,用于渲染当前路由的子路由组件。

const router = createBrowserRouter([{
  path: '/',
  Component: Layout,
  children: [{
    path: '/page1',
    Component: Page1,
  }],
}, {
  path: '*',
  Component: NotFound,
}])

------分割线-----

function Layout() {
  return (
    <div>
      <ul>
        <li>
          <Link to="/page1">page1</Link>
        </li>
      </ul>
      <Outlet />
    </div>
  );
}

路由按需加载 借助react的lazySuspense可以轻松的实现按需加载。

const router = createBrowserRouter([
  {
    path: '/',
    Component: Layout,
    children: [
      {
        path: '/page1',
        Component: lazy(() => import('./pages/page1/index.tsx')),
      }
    ],
  },
  {
    path: '*',
    Component: NotFound,
  }
])

Outlet组件需要用Suspense包起来,再加上一个loading。

<Suspense fallback={<div>Loading ...</div>}>
  <Outlet />
</Suspense>