react-router-dom v6 路由实现动态修改document.title

1,353 阅读1分钟

项目中需要在对应的路由界面 设置不同的网址 title。这里使用 v6 简单实现一下

路由表:

const routers: RouteConfig = [
  {
    element: <PrivateRoute />,
    children: [
      {
        path: '/',
        element: <MenuManager />,
        children: [
          {
            path: 'share',
            meta: {
              title: '共享列表'
            },
            element: <TableRightMenuContext />,
          },
          {
            path: 'template',
            meta: {
              title: '常用模板'
            },
            children: [],
            element: <Template />
          }
        ]
      }
    ]
  },
  {
    path: '/login',
    meta: {
      title: '登录'
    },
    element: <Loginelement />
  },
  {
    path: '/402',
    element: <Error402 />
  },
  {
    path: '/404',
    element: <Error404 />
  },
  {
    path: '/500',
    element: <Error500 />
  }
];

渲染路由

function debounce(fn: Function, delay: number) {
  let timer: any = null;
  return function (...parmas: any) {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.apply(null, parmas)
    }, delay);
  }
}

function getMetaFromPath(path: string, routes: RouteConfig): null | { title?: string | undefined } {
  // 遍历路由配置数组
  for (const route of routes) {
    // 如果路径匹配到当前路由的path属性
    if (route.path === path || route.path === path.split('/')[1]) {
      // 返回当前路由的meta属性(如果存在)
      return route?.meta || null;
    }

    // 如果当前路由有子路由(children),则递归调用getMetaFromPath函数获取子路由的meta信息
    if (route.children) {
      const meta = getMetaFromPath(path, route.children);
      if (meta !== null) {
        return meta;
      }
    }
  }
  // 如果没有找到匹配的路由,返回null
  return null;
}

const dbSetDoucumentTitle = debounce((pathname: string) => {
  const meta = getMetaFromPath(pathname, routers);
  if (meta?.title) {
    document.title = meta.title;
    return;
  }
  document.title = window.projectBaseName.split('/')[1];
}, 100);

export const Routers = () => {
  const router = useRoutes(routers as (RouterConfigProps & NonIndexRouteObject)[])!;
  const location = useLocation();

  //  路由变化 router 会变化
  useEffect(() => { dbSetDoucumentTitle(location.pathname) }, [router]);
  return router;
};

app.tsx

function App() {
  return (
    <div className="App">
      <EventBusProvider>
        <ConfigProvider>
          <AuthProvider>
            <Suspense fallback={<>。。。</>}>
              <BrowserRouter basename='/manager'>
                <Routers />
              </BrowserRouter>
            </Suspense>
          </AuthProvider>
        </ConfigProvider>
      </EventBusProvider>
    </div>
  );
}