Autumn_Ning_Blog icon indicating copy to clipboard operation
Autumn_Ning_Blog copied to clipboard

React Router V4 入坑指南

Open wangning0 opened this issue 7 years ago • 0 comments

React Router v4出来很久了,你们觉得它好用么?

思维上的转变

在我看来,ReactRouter V4虽然已经出来很久了,但是并没有在前端圈内掀起热潮,当我从原来的V3版本切换到了现在的V4版本之后,用的非常不顺心,不仅仅是它的API进行了颠覆式的改变,更值得去改变的而是V3 => V4理念上的改变————遵循一切都是组件的思维,React Router V4提供的Route Link Switch等都是组件

我们原来写router的配置的时候,一般都会把所有的配置写在一个文件内,来进行管理路由,但是在V4版本的ReactRouter中,我们不能再使用这样的思维,不然,再复杂的页面的路由处理上会非常的蛋疼(心里苦)。

原来的V3版本的ReactRouter中,我们可以根据Route的嵌套关系来进行路由之间的嵌套,然后在使用this.props.children来直接引入到Component/Containers中即可,但是在V4版本中,就不能直接通过这种方式来使用了。

// V3
<Route path="/" component={Page}>
    <Route path="app" component={App}>
        <Route path="create" component={Create} />
        
    </Route>
</Route>
// V4
<Router>
    <Layout> //自己定义的组件
        <Switch>
            <Route path="/some-path" component={SomeComponent} />
        </Switch>
    </Layout>
</Router>

以及原来的动态的路由的方式也变了,在V3版本中,我们直接通过browserHistory.push的方法 来进行动态的路由的跳转即可,但是在V4版本中,我们就不能这么用了,而必须要通过withRouter高阶组件的方式去进行路由的跳转

// V3
import browserHistory from 'react-router';

export function addProduct(props) {
  return dispatch =>
    axios.post(`xxx`, props, config)
      .then(response => {
        browserHistory.push('/cart'); //这里
      });
}
// V4
import React from "react";
import {withRouter} from "react-router-dom";

class MyComponent extends React.Component {
  ...
  myFunction() {
    this.props.history.push("/some/Path");
  }
  ...
}
export default withRouter(MyComponent);

一个实际的需求

假设现在需要有三个路由,一个登陆,一个首页,一个创建订单,登录页面是一个单独的页面,没有和其他页面共有任何组件,首页和创建订单页共有Header Nav等组件,只有页面的大肚子中间部分是内容不同的。那么要保证在首页和订单页切换的过程中,确保Header Nav等公共组件的不会重新卸载和挂载。

这种需求在实际上,应该是一个比较实用的场景,在使用V3版本的ReactRouter中我们应该很快就能够想到路由的配置,但是在V4版本中,如果还一直抱着this.props.chidren这种思维去想,以及因为V4规定一个Router下只能有一个子元素,来进行路由的配置就会很蛋疼,所以在V4的使用过程中,一定要抛弃原来的思维,要把它看成是一个普通的组件来看待,当然,有些大的路由配置还是建议放在一起进行统一的管理

所以,给出下面我对这个的实现

// routers.js
// ...
 <Router>
   <Switch>
       <Route path="/index" component={App} />
       <Route exact path="/login" component={Login} />
       <Redirect from="/" to="/index" />
   </Switch>
 </Router>
// ...
// App.js
// ...
class App extends Component {
  render() {
    const user = this.props.user
    return (
      <div className="App">
        <Header 
          user={user}
        />
        <Nav />
       <Switch>
          <Route exact path="/index/create" render={() => <div>创建项目</div>}></Route>
          <Route render={() => <div>首页</div>}></Route>
       </Switch>
      </div>
    )
  }
}
// ...

如果你有什么更好的解决方案 请留言,谢谢!

wangning0 avatar Dec 26 '17 08:12 wangning0