目录
今天上午线上系统遇到了一个前端菜单点击的bug,记录一下采坑经历,经验共享大家。
现象
线上某2级菜单,点击进不去页面了,会自动重定向到默认菜单。
原因分析
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
class App extends Component {
render() {
return (
<div className="App">
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/topics">Topics</Link>
</li>
</ul>
<hr />
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/topics" component={Topics} />
</div>
</Router>
</div>
);
}
}
function Home() {
return (
<div>
<h2>Home</h2>
</div>
);
}
function About() {
return (
<div>
<h2>About</h2>
</div>
);
}
class Topics extends Component {
componentDidMount() {
console.log(this);
}
render() {
const { match } = this.props;
return (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>Rendering with React</Link>
</li>
<li>
<Link to={`${match.url}/components`}>Components</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>Props v. State</Link>
</li>
</ul>
<Route path={`${match.path}/:topicId`} component={Topic} />
<Route
exact
path={match.path}
render={() => <h3>Please select a topic.</h3>}
/>
</div>
)
}
}
class Topic extends Component {
render() {
const { match } = this.props;
return (
<div>
<h3>{match.params.topicId}</h3>
</div>
);
}
}
export default App;
从react-router-dom引入的Route附件,Route的位置代表了所对应的component显示的位置,这一点很重要
Topics 所对应的路由组件下又进行了Route的设置,并且在子组件Topic的路由配置中拿到父组件的相对路径match.url,这种写法有利于路由组件的维护,即使改变了层级,子路由的path也不用改变,需要注意当时组件是否有传入路由参数。
关于 RouteProps exact 属性
export interface RouteProps<
Path extends string = string,
Params extends { [K: string]: string | undefined } = ExtractRouteParams<Path, string>
> {
location?: H.Location | undefined;
component?: React.ComponentType<RouteComponentProps<any>> | React.ComponentType<any> | undefined;
render?: ((props: RouteComponentProps<Params>) => React.ReactNode) | undefined;
children?: ((props: RouteChildrenProps<Params>) => React.ReactNode) | React.ReactNode | undefined;
path?: Path | readonly Path[] | undefined;
exact?: boolean | undefined;
sensitive?: boolean | undefined;
strict?: boolean | undefined;
}
export class Route<T extends {} = {}, Path extends string = string> extends React.Component<
RouteProps<Path> & OmitNative<T, keyof RouteProps>,
any
> {}
export interface RouterProps {
children?: React.ReactNode;
history: H.History;
}
export class Router extends React.Component<RouterProps, any> {}
经验总结
关于Route的exact,加上exact代表当前路由path的路径采用精确匹配,比如说Home的path如果不加上exact,那么path="/about"将会匹配他自己与path="/“这两个,所以一般path=”/"这个路由一般会加上exact.
另外需要注意一点的是嵌套路由不要加exact属性:
如果父级路由加上,这里例如topics加上该属性,他下面的子路由将不会生效,因为外层强制匹配了。
react-router总体来讲配置还是挺复杂的,需要提前构思好整个路由如何搭建,望诸君多多尝试.