bump
This commit is contained in:
parent
6d52707ad3
commit
bdf6243bd9
@ -30,7 +30,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"tailwind-merge": "^3.1.0"
|
"tailwind-merge": "^3.2.0"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
107
src/router/index.tsx
Normal file
107
src/router/index.tsx
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import React, { createContext, useContext, useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
// 路由上下文
|
||||||
|
type RouterContextType = {
|
||||||
|
pathname: string;
|
||||||
|
navigate: (to: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RouterContext = createContext<RouterContextType | null>(null);
|
||||||
|
|
||||||
|
// 使用路由上下文的Hook
|
||||||
|
export const useRouter = () => {
|
||||||
|
const context = useContext(RouterContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('useRouter必须在RouterProvider内部使用');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 路由项定义
|
||||||
|
export type RouterItem = {
|
||||||
|
path: string;
|
||||||
|
element: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Router组件 - 路由系统的根组件
|
||||||
|
type RouterProps = {
|
||||||
|
routes?: RouterItem[];
|
||||||
|
children?: React.ReactNode;
|
||||||
|
};
|
||||||
|
export const Route = ({ path, element }: RouteProps) => {
|
||||||
|
return <>{element}</>;
|
||||||
|
};
|
||||||
|
export const Router = ({ routes, children }: RouterProps) => {
|
||||||
|
const [pathname, setPathname] = useState(window.location.pathname);
|
||||||
|
|
||||||
|
// 导航方法
|
||||||
|
const navigate = (to: string) => {
|
||||||
|
window.history.pushState(null, '', to);
|
||||||
|
setPathname(to);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听浏览器前进后退
|
||||||
|
useEffect(() => {
|
||||||
|
const handlePopState = () => {
|
||||||
|
setPathname(window.location.pathname);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('popstate', handlePopState);
|
||||||
|
return () => window.removeEventListener('popstate', handlePopState);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RouterContext.Provider value={{ pathname, navigate }}>
|
||||||
|
<Routes>
|
||||||
|
{routes?.map((route, index) => (
|
||||||
|
<Route key={index} path={route.path} element={route.element} />
|
||||||
|
))}
|
||||||
|
{children}
|
||||||
|
</Routes>
|
||||||
|
</RouterContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Route组件 - 定义单个路由
|
||||||
|
type RouteProps = {
|
||||||
|
path: string;
|
||||||
|
element: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Routes组件 - 渲染匹配的路由
|
||||||
|
type RoutesProps = {
|
||||||
|
children: React.ReactNode | React.ReactNode[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Routes = ({ children }: RoutesProps) => {
|
||||||
|
const { pathname } = useRouter();
|
||||||
|
|
||||||
|
// 将children转换为数组处理
|
||||||
|
const childrenArray = React.Children.toArray(children);
|
||||||
|
|
||||||
|
// 查找匹配的路由
|
||||||
|
const matchedRoute = childrenArray.find((child) => {
|
||||||
|
if (React.isValidElement(child) && typeof child.type === 'function') {
|
||||||
|
const routeProps = child.props as RouteProps;
|
||||||
|
|
||||||
|
// 简单路径匹配,可以扩展为支持参数等更复杂功能
|
||||||
|
if (routeProps.path === pathname || (routeProps.path === '/' && pathname === '')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支持通配符路由
|
||||||
|
if (routeProps.path.endsWith('*') && pathname.startsWith(routeProps.path.slice(0, -1))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 返回匹配的路由元素或空
|
||||||
|
if (matchedRoute && React.isValidElement(matchedRoute)) {
|
||||||
|
// @ts-ignore
|
||||||
|
return <>{matchedRoute.props?.element}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user