npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vlian/router

v1.0.16

Published

基于 React Router 的路由管理包,支持动态路由、权限控制、路由转换等功能

Downloads

1,349

Readme

@vlian/router

基于 React Router 的高级路由管理包,支持动态路由、权限控制、路由转换等功能。

📦 安装

npm install @vlian/router
# 或
pnpm add @vlian/router
# 或
yarn add @vlian/router

🔧 依赖要求

本项目需要以下 peer dependencies:

  • react: ^19.2.0
  • react-dom: ^19.2.0
  • react-router-dom: ^7.0.0
  • @ant-design/cssinjs: >=1.24.0
  • classnames: >=2.3.0

✨ 特性

  • 🚀 动态路由加载 - 支持从 API 动态获取路由配置
  • 🔐 权限控制 - 支持基于角色和登录状态的权限控制
  • 🎨 布局系统 - 灵活的布局配置,支持嵌套布局
  • 懒加载 - 路由组件自动懒加载,优化首屏性能
  • 🔄 路由转换 - 将自定义路由格式自动转换为 React Router 格式
  • 📱 子应用支持 - 支持微前端子应用模式
  • 🎯 类型安全 - 完整的 TypeScript 类型定义
  • 🎭 加载状态 - 内置加载动画,支持自定义加载组件
  • 🛡️ 错误处理 - 支持自定义错误边界组件
  • 📋 菜单生成 - 自动从路由配置生成菜单数据

📖 使用指南

基础用法

import { RouterProvider } from '@vlian/router';
import type { RouteItem } from '@vlian/router';

// 定义路由组件导入映射
const imports = {
  // 页面组件
  pages: {
    root: () => import('./pages/Root'),
    home: () => import('./pages/Home'),
    about: () => import('./pages/About'),
    '404': () => import('./pages/NotFound'),
  },
  // 布局组件
  layouts: {
    root: () => import('./layouts/RootLayout'),
    admin: () => import('./layouts/AdminLayout'),
  },
  // 加载组件
  loadings: {
    root: () => import('./components/Loading'),
  },
  // 错误组件
  errors: {
    root: () => import('./components/ErrorBoundary'),
  },
};

// 获取动态路由的函数
const fetchRoutes = async (): Promise<RouteItem[]> => {
  const response = await fetch('/api/routes');
  return response.json();
};

function App() {
  return (
    <RouterProvider
      fetchRoutes={fetchRoutes}
      imports={imports}
    />
  );
}

路由配置格式

路由配置使用 RouteItem 类型,支持以下字段:

type RouteItem = {
  // 布局组件的 key(对应 imports.layouts 中的键)
  layout?: string | null;
  
  // 页面组件的 key(对应 imports.pages 中的键)
  page?: string | null;
  
  // 加载组件的 key(对应 imports.loadings 中的键)
  loading?: string | null;
  
  // 错误组件的 key(对应 imports.errors 中的键)
  errors?: string | null;
  
  // 路由名称,唯一标识
  name: string;
  
  // 路由路径
  path: string | undefined;
  
  // 是否为分组路由(不渲染自身,只作为容器)
  isGroup?: boolean;
  
  // 是否启用重定向到第一个子路由
  enableRedirection?: boolean;
  
  // 路由元数据
  handle: RouteItemHandle;
  
  // 子路由
  children?: RouteItem[];
};

type RouteItemHandle = {
  // 路由标题
  title: string;
  
  // 国际化 key
  i18nKey?: string;
  
  // 排序顺序
  order: number;
  
  // 图标
  icon?: string;
  
  // 在菜单中隐藏
  hideInMenu?: boolean;
  
  // 隐藏页脚
  hideFooter?: boolean;
  
  // 保活(Keep Alive)
  keepAlive?: boolean;
  
  // 是否需要登录
  needLogin?: boolean;
  
  // 允许访问的角色列表
  roles?: string[];
  
  // 其他自定义字段
  [key: string]: unknown;
};

路由配置示例

const routes: RouteItem[] = [
  {
    name: 'home',
    path: '/home',
    page: 'home',
    layout: 'root',
    handle: {
      title: '首页',
      order: 1,
      icon: 'home',
      needLogin: true,
    },
  },
  {
    name: 'admin',
    path: '/admin',
    layout: 'admin',
    isGroup: true,
    enableRedirection: true,
    handle: {
      title: '管理后台',
      order: 2,
      icon: 'admin',
      roles: ['admin'],
    },
    children: [
      {
        name: 'admin-users',
        path: '/admin/users',
        page: 'adminUsers',
        handle: {
          title: '用户管理',
          order: 1,
        },
      },
      {
        name: 'admin-settings',
        path: '/admin/settings',
        page: 'adminSettings',
        handle: {
          title: '系统设置',
          order: 2,
        },
      },
    ],
  },
];

使用路由 Hook

import { useRoute } from '@vlian/router';

function MyComponent() {
  const route = useRoute();
  
  // route 包含以下信息:
  // - id: 路由 ID
  // - pathname: 当前路径
  // - search: 查询字符串
  // - hash: 哈希值
  // - query: 解析后的查询参数对象
  // - fullPath: 完整路径(pathname + search + hash)
  // - handle: 路由元数据
  // - data: 路由数据(来自 loader)
  
  return (
    <div>
      <h1>{route.handle?.title}</h1>
      <p>当前路径: {route.pathname}</p>
      <p>查询参数: {JSON.stringify(route.query)}</p>
    </div>
  );
}

使用导航工具

在子应用模式下,可以通过 window.$router 访问导航工具:

// 导航到指定路径
window.$router.push('/home');

// 带查询参数导航
window.$router.push('/users', { page: 1, size: 10 });

// 替换当前历史记录
window.$router.replace('/login');

// 返回上一页
window.$router.back();

// 前进
window.$router.forward();

// 跳转到首页
window.$router.goHome();

// 向上导航(父路由)
window.$router.navigateUp();

// 重新加载
window.$router.reload();

// 使用 React Router 的 navigate 方法
window.$router.navigate('/path', { replace: true });

生成菜单数据

import { formatMenusDate } from '@vlian/router';
import { useRoute } from '@vlian/router';

function Menu() {
  const route = useRoute();
  // 假设你有路由数据
  const routes = route.dynamicRoutes || [];
  const menus = formatMenusDate(routes);
  
  return (
    <ul>
      {menus.map(menu => (
        <li key={menu.key}>
          <a href={menu.path}>{menu.name}</a>
          {menu.children && (
            <ul>
              {menu.children.map(subMenu => (
                <li key={subMenu.key}>
                  <a href={subMenu.path}>{subMenu.name}</a>
                </li>
              ))}
            </ul>
          )}
        </li>
      ))}
    </ul>
  );
}

RouterProvider 配置选项

<RouterProvider
  // 必需:获取动态路由的函数
  fetchRoutes={fetchRoutes}
  
  // 必需:组件导入映射
  imports={imports}
  
  // 可选:根路由配置(默认使用内置配置)
  rootRoutes={customRootRoutes}
  
  // 可选:静态路由(默认包含 404 路由)
  staticRoutes={customStaticRoutes}
  
  // 可选:React Router 配置选项
  options={{
    future: {
      v7_startTransition: true,
      v7_relativeSplatPath: true,
    },
  }}
  
  // 可选:是否为子应用模式(默认 false)
  isSubApp={false}
  
  // 可选:自定义加载组件
  loadingRender={<CustomLoading />}
  
  // 可选:加载动画大小(默认 '24px')
  loadingSize="32px"
  
  // 可选:加载动画颜色(默认 'currentColor')
  loadingColor="#1890ff"
  
  // 可选:加载动画透明度(默认 0.25)
  loadingOpacity={0.3}
/>

🎨 组件导出

RouterProvider

路由提供者组件,用于初始化和管理路由系统。

Hooks

  • useRoute<T>() - 获取当前路由信息
  • useRouterTransform() - 路由转换 Hook(内部使用)

工具函数

  • navigator(router) - 创建导航工具对象
  • formatMenusDate(routes) - 将路由配置格式化为菜单数据

🔍 类型定义

主要类型定义:

  • RouteItem - 路由项类型
  • RouteItemHandle - 路由元数据类型
  • RouteMapType - 路由组件映射类型
  • RouterProviderProps - RouterProvider 属性类型
  • RouterContextType - 路由上下文类型
  • FormattedMenuItem - 格式化后的菜单项类型

🚀 高级用法

自定义根路由

import { RouteItem } from '@vlian/router';

const customRootRoutes: RouteItem = {
  name: 'root',
  path: '/',
  page: 'root',
  layout: 'customRoot',
  handle: {
    title: '应用根',
    order: 0,
  },
  children: [],
};

<RouterProvider
  fetchRoutes={fetchRoutes}
  imports={imports}
  rootRoutes={customRootRoutes}
/>

自定义静态路由

import { RouteItem } from '@vlian/router';

const customStaticRoutes: RouteItem[] = [
  {
    name: '403',
    path: '/403',
    page: 'forbidden',
    handle: {
      title: '无权限',
      order: 99999997,
    },
  },
  {
    name: '404',
    path: '/404',
    page: 'notFound',
    handle: {
      title: '页面不存在',
      order: 99999998,
    },
  },
  {
    name: 'notFound',
    path: '*',
    page: 'notFound',
    handle: {
      title: '页面不存在',
      order: 99999999,
    },
  },
];

<RouterProvider
  fetchRoutes={fetchRoutes}
  imports={imports}
  staticRoutes={customStaticRoutes}
/>

子应用模式

在微前端场景中,可以启用子应用模式,通过 window.$router 访问路由导航:

<RouterProvider
  fetchRoutes={fetchRoutes}
  imports={imports}
  isSubApp={true}
/>

📝 注意事项

  1. 路由名称唯一性:每个路由的 name 字段必须唯一,它作为路由的唯一标识符。

  2. 组件导出格式:所有通过 imports 导入的组件必须使用默认导出,例如:

    // ✅ 正确
    export default function MyPage() { ... }
       
    // ❌ 错误
    export function MyPage() { ... }
  3. 布局和页面

    • 如果路由有 layout 且不是分组路由,会使用布局组件包裹页面
    • 如果路由有 page 且有子路由,会自动创建 index 路由来渲染页面
    • 分组路由(isGroup: true)不会渲染自身,只作为子路由的容器
  4. 路由排序:子路由会根据 handle.order 自动排序,数值越小越靠前。

  5. 权限控制:当前版本的路由转换支持权限相关的元数据配置,但具体的权限验证逻辑需要在业务层面实现。

🤝 贡献

欢迎提交 Issue 和 Pull Request!

📄 许可证

MIT

🔗 相关链接