• react router


    官方文档 https://react-router.docschina.org/web/guides/quick-start

    history 对象是可变的,因此我们建议从 <Route> 的渲染选项中来访问 location,而不是从 history.location 直接获取。这样做可以保证 React 在生命周期中的钩子函数正常执行,例如:

    // locationChanged 将为 true
    const locationChanged = nextProps.location !== this.props.location

    // INCORRECT,因为 history 是可变的所以 locationChanged 将一直为 false
    const locationChanged = nextProps.history.location !== this.props.history.location

    使用总结 https://www.cnblogs.com/V587Chinese/p/11507836.html

    BrowserRouter和HashRouter
    这两者可以理解为路由的作用域,所有的Link组件和Route组件都必须在其内部。二者区别在于:

    • BrowserRouter中的URL指向真实的url,当页面刷新(或直接操作url并回车)时,将产生指向该路径的url请求,如果服务器端没有配置该路径,则返回404。
    • HashRouter中#后面的uri并不是真实的请求路径,对于后端来说,全都指向同一个地址。另外哈希历史记录不支持loaction.key和loaction.state,当通过state传递参数的时候,无法从历史记录中获取到,可能会导致页面显示异常。
    • 也就是说在浏览器地址栏中直接输入 http://test.code.com/aboutBrowserRouter会匹配不了而报404(因为服务端nginx中只配置了test.code.com,BrowserRouter代码中的路由并不会被服务端识别),而 http://test.code.com/#/aboutHashRouter会正常显示about页面(因为访问的后端地址仅仅是test.code.com)。

    在BrowserRouter模式下,如何在服务端配置呢?

    • Nginx配置(前端项目打包),将任何URL访问都指向index.html
    • 后端服务配置(前端项目打包),将任何URL访问都指向index.html
    • 开启前端服务(需要进行Nginx反向代理)

    Link标签和a标签,看到的效果是一样的,但我们推荐<Link>,使用它才是单页面应用,浏览器不会请求页面;而使用a标签,会重新请求页面。

    导航守卫的实现(权限校验)

    NavLink 和  PureComponent 一起使用的时激活链接样式不生效 https://www.cnblogs.com/wenruo/p/10321456.html

    v4 v3区别及策略 https://zhuanlan.zhihu.com/p/28585911

    1、嵌套布局

    const PrimaryLayout = props => {
      return (
        <div className="primary-layout">
          <PrimaryHeader />
          <main>
            <Switch>
              <Route path="/" exact component={HomePage} />
              <Route path="/user" component={UserSubLayout} />
              <Route path="/products" component={ProductSubLayout} />
              <Redirect to="/" />
            </Switch>
          </main>
        </div>
      );
    };
    
    const UserSubLayout = () =>
      <div className="user-sub-layout">
        <aside>
          <UserNav />
        </aside>
        <div className="primary-content">
          <Switch>
            <Route path="/user" exact component={BrowseUsersPage} />
            <Route path="/user/:userId" component={UserProfilePage} />
          </Switch>
        </div>
      </div>;
    
    const UserSubLayout2 = props =>
      <div className="user-sub-layout">
        <aside>
          <UserNav />
        </aside>
        <div className="primary-content">
          <Switch>
            <Route path={props.match.path} exact component={BrowseUsersPage} />
            <Route
              path={`${props.match.path}/:userId`}
              component={UserProfilePage}
            />
          </Switch>
        </div>
      </div>;
    const UserSubLayou3 = ({ match }) =>
      <div className="user-sub-layout">
        <aside>
          <UserNav />
        </aside>
        <div className="primary-content">
          <Switch>
            <Route exact path={match.path} component={BrowseUsersPage} />
            <Route path={`${match.path}/add`} component={AddUserPage} />
            <Route path={`${match.path}/:userId/edit`} component={EditUserPage} />
            <Route path={`${match.path}/:userId`} component={UserProfilePage} />
    <Route component={NoMatch} /> </Switch> </div> </div>;
    // 注意上面的route顺序,因为switch只匹配一个,需要将更精确的放到前面。另一种方式是每一个route都加exact精确匹配。

    我们用 2 个 routes 替换之前的 4 个 routes
    注意,这里我们没有再使用 exact,因为,我们希望 /user 可以匹配任何以 /user 开始的 route,products 同理。
    使用这种策略,子布局也开始承担起了渲染 routes 的责任。避免两个 user组件页面中都有一个<UserNav />的重复渲染问题。

    有一点值得注意的是,routes 需要识别它的完整路径才能匹配,为了减少我们的重复输入,我们可以使用 props.match.path来代替。match.url 是浏览器 URL 的一部分,match.path 是我们为 router 书写的路径

    2、Authorized Route 路由权限控制

    在应用程序中限制未登录的用户访问某些路由是非常常见的,还有对于授权和未授权的用户 UI 也可能大不一样,为了解决这样的需求,我们可以考虑为应用程序设置一个主入口,如/auth表示有权限相关操作,/app表示业务操作。
    现在,我们首先会去选择应用程序在哪个顶级布局中,比如,/auth/login 和 /auth/forgot-password 肯定在 UnauthorizedLayout 中,另外,当用户登陆时,我们将判断所有的路径都有一个 /app 前缀以确保是否登录。如果用户访问 /app 开头的页面但并没有登录,我们将会重定向到登录页面。示例:

    class App extends React.Component {
      render() {
        return (< Provider store={
          store
        } > <BrowserRouter > <Switch > <Route path="/auth" component={
          UnauthorizedLayout
        }
        />
          <AuthorizedRoute path="/app " component={PrimaryLayout} />
        </Switch>
          </BrowserRouter>
        </Provider>
        )
      }
    }
    
    class AuthorizedRoute extends React.Component {
      componentWillMount() {
        getLoggedUser();
      }
    
      render() {
        const { component: Component, pending, logged, ...rest } = this.props;
        return (
          <Route
            {...rest}
            render={props => {
              if (pending) return <div>Loading...</div>;
              return logged
                ? <Component {...this.props} />
                : <Redirect to=" / auth / login " />;
            }}
          />
        );
      }
    }
    
    const stateToProps = ({ loggedUserState }) => ({
      pending: loggedUserState.pending,
      logged: loggedUserState.logged
    });
    
    export default connect(stateToProps)(AuthorizedRoute);

    另外可参考:导航守卫的实现

  • 相关阅读:
    表单自动填充autocomplete的兼容性方案
    函数的默认参数值
    利用zookeeper搭建hadoop HA集群
    zookeeper设置开机启动项
    zookeeper集群挂了的恢复流程
    zookeeper集群搭建
    docker 安装ElasticSearch的中文分词器IK
    [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
    把mysql服务设置开机启动项
    docker-compose的使用
  • 原文地址:https://www.cnblogs.com/ccdat/p/11619249.html
Copyright © 2020-2023  润新知