react语法 - 给vue开发者
Dva - react状态管理 - 给vuex开发者
Redux - 给vue开发者
最新版本是 5.x,网上很多文档都是老版本的,已经不再适用(包括这个和这个)。官方 API(英文的。。。),PrivateRoute 用法
npm install react-router-dom --save
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
ReactDOM.render(
<Router>
<Switch>
<Route path="/" exact component={App} />
<Route path="/use" component={AppUsexxx} />
<Route path="/other" component={Other} />
<Route component={404} />
</Switch>
</Router>,
document.getElementById("root")
);
借助插件react-router-config
可以实现VUE式的路由定义
import { renderRoutes } from 'react-router-config';
const Child = ({ route }) => ( // 接收 route 参数
<div>
<h2>Child</h2>
{/* vue router-view */}
{renderRoutes(route.routes, { someProp: "these extra props are optional" })}
</div>
);
const routes = [
{
component: Root,
routes: [
{ path: '/', exact: true, component: Home },
{
path: '/child/:id',
component: Child,
routes: [{ path: '/child/:id/grand-child', component: GrandChild }],
},
],
},
];
ReactDOM.render(
<BrowserRouter>
{renderRoutes(routes)}
</BrowserRouter>,
document.getElementById('root')
);
路由嵌套
// Other.tsx
import React from "react";
import { Route, Switch, useRouteMatch } from "react-router-dom";
import Message from "./Message";
const Other: React.FC = (props: any) => {
let match = useRouteMatch();
return (
<div>
<h1>啥嘻嘻</h1>
{/* 路由嵌套 */}
<Switch>
<Route path={`${match.path}/msg/:id`}>
<Message></Message>
</Route>
</Switch>
</div>
);
};
export default Other;
在根部定义所有路由
ReactDOM.render(
<Router>
<Switch>
<Route path="/" exact component={App} />
<Route path="/use" component={AppUsexxx} />
<Route
path="/other"
component={() => (
<Other>
<Route path="/other/msg/:id" component={Message} />
</Other>
)}
></Route>
<Route component={404} />
</Switch>
</Router>,
document.getElementById("root")
);
const Other: React.FC = (props: any) => {
return (
<div>
<h1>啥嘻嘻</h1>
{props.children}
);
};
很不方便。
vue-router 与 react-router 对照表
vue-router | react-router |
---|---|
根部 new Vue({ route }) 注入 | ReactDOM.render 方法 html 外层加入 Router 等标签 |
借助react-router-config 可实现VUE式配置路由文件 |
|
mode | <BrowserRouter>和<HashRouter> |
base | basename |
路由配置 |
<Route>和<Switch> 可以用在任何位置,路由嵌套写在具体组件里 |
router-link 标签 | Link、NavLink |
router-view 标签 | props.children 或直接写要使用的组件<br />orreact-router-config renderRoutes(route.routes, {...someprops}) |
this.$route.params.id | useParams().id |
this.$router.push、replace() | useHistory().push、replace()、Redirect 标签 |
路由守卫 | 没有,需要自己写。 |
.
-
Switch 的作用:仅渲染匹配的第一个。不使用它时会渲染所有的匹配项(eg: /use 会渲染 /和/use 两个组件)
-
路由对象(link 的 to、push 的参数):
{ "pathname": "/path", "search": "?name=val", "hash": "#the-hash", "state": { "fromDashboard": true } }
代码拆分 例子,及路由嵌套的另一种实现
cnpm install @loadable/component --save-dev
// .d.ts 声明文件,非必须
npm i --save-dev @types/loadable__component
添加代码拆分,并封装 router,可以像配置 vue 一样配置路由
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import loadable from "@loadable/component";
export type RouteType = {
path?: string,
component: string,
exact?: boolean,
children?: RouteType[],
};
const CreateRoute = (route: RouteType, fatherPath: string = "") => {
const Comp = loadable(() => import(`../pages${route.component}`));
const path = route.path ? `${fatherPath}${route.path}` : undefined;
return (
<Route
path={path}
exact={route.exact || false}
component={() => (
<Comp>
{route.children &&
route.children.length &&
route.children.map((item) => CreateRoute(item, path || fatherPath))}
</Comp>
)}
></Route>
);
};
const CreateRouter = (config: RouteType[]) => {
return (
<Router>
<Switch>{config.map((item) => CreateRoute(item))}</Switch>
</Router>
);
};
export default CreateRouter;
使用
import CreateRouter from "./router/router"; // 上面那段代码
const routers = [
{
path: "/",
component: "/App",
exact: true,
},
{
path: "/use",
component: "/AppUsexxx",
},
{
path: "/other",
component: "/Other",
children: [
{
path: "/msg/:id",
component: "/Message",
},
],
},
];
ReactDOM.render(
<Provider store={store}>{CreateRouter(routers)}</Provider>,
document.getElementById("root")
);
路由守卫 例子
- 利用高阶函数封装组件,在 HOC 内部做权限判断,不满足条件 useHistory().replace 掉
function withAuth(Comp, isLogin) {
// ...并返回另一个组件...
return class extends React.Component {
render() {
if (isLogin) {
return <Comp data={this.state...} />;
} else {
return <Redirect to="/login" />;
}
}
};
}
// or ? (这段代码没有验证过)
function RouteGuard({ children }) {
if (isLogin) return children
return <Redirect to="/login" />;
}
ReactDOM.render(
<BrowserRouter>
<Router basename={'/'}>
<RouteGuard>{renderRoutes(routes)}</RouteGuard>
</Router>
</BrowserRouter>,
document.getElementById('root')
);
- 封装一个自定义 Route 组件
class PrivateRoute extends Component {
render() {
const { path, component } = this.props;
if (isLogin) {
return <Route path={path} component={component} />;
}
return <Redirect to={"/login"} />;
}
}
// <Route path="/other" component={Other} />
<PrivateRoute path="/other" component={Other} />;
网友评论