ant design pro 代码学习(一) ----- 路由分析

1、一级路由

 const routerData = getRouterData(app);
  const UserLayout = routerData['/user'].component;
  const BasicLayout = routerData['/'].component;
  return (
    <LocaleProvider locale={zhCN}>
      <ConnectedRouter history={history}>
        <Switch>
          <Route path="/user" component={UserLayout} />
          <AuthorizedRoute
            path="/"
            render={props => <BasicLayout {...props} />}
            authority={['admin', 'user']}
            redirectPath="/user/login"
          />
        </Switch>
      </ConnectedRouter>
    </LocaleProvider>
  );

  整个项目的路由分两部分:一部分是user相关的,一部分是业务相关的

  • 含有/user的路由 — 对应的路由组件时UserLayout
  • 排除/user外的路由 — 对应的路由组件时BasicLayout

2、二级路由

  • UserLayout
      UserLayout中设置了二级路由,其中match.path对应为props属性中的match.path,此处即为/user,routerData为所有的路由数据,详见(src/common/router.js),getRoutes(match.path, routerData)方法获取所有的user相关的路由配置,并生成对应的路由组件。同时Redirect组件设置了默认的路由。
<Switch>
  {getRoutes(match.path, routerData).map(item => (
    <Route
      key={item.key}
      path={item.path}
      component={item.component}
      exact={item.exact}
    />
  ))}
  <Redirect exact from="/user" to="/user/login" />
</Switch>
  • BasicLayout
      所有相关的路由信息,都包含有侧边栏、顶部菜单、内部部分、底部等布局,即SiderMenu、Header、Content、Footer。路由的布局则部署在content组件中,同UserLayout,通过getRoutes获取相关路由的信息,并生成队友路由组件route。
<Layout>
        <SiderMenu/>
        <Layout>
          <Header>
            <GlobalHeader/>
          </Header>
          <Header>
           <Content>
            <Switch>
              {redirectData.map(item => (
                <Redirect key={item.from} exact from={item.from} to={item.to} />
              ))}
              {getRoutes(match.path, routerData).map(item => (
                <AuthorizedRoute
                  key={item.key}
                  path={item.path}
                  component={item.component}
                  exact={item.exact}
                  authority={item.authority}
                  redirectPath="/exception/403"
                />
              ))}
              <Redirect exact from="/" to={bashRedirect} />
              <Route render={NotFound} />
            </Switch>
          </Content>
          <Footer>
            <GlobalFooter/>
          </Footer>
        </Layout>
      </Layout>

  当前路由集合中第一个通过认证的路由被设置为默认的路由,即Redirect的指向


3、路由认证 AuthorizedRoute

   BasicLayout中路由都是循环生成AuthorizedRoute组件完成,包括我们的一级路由也是通过AuthorizedRoute组件封装的,那么AuthorizedRoute到底是干嘛的?

//BasicLayout.js
import Authorized from '../utils/Authorized';
const { AuthorizedRoute, check } = Authorized;

   由以上代码可知,AuthorizedRoute是Authorized组件的一个属性。在../utils/Authorized.js中我们可以找到如下代码。其中getAuthority()获取用户存放在localStorage的权限记录。Authorized是由RenderAuthorized(getAuthority())生成。

//../utils/Authorized.js
import RenderAuthorized from '../components/Authorized';
import { getAuthority } from './authority';
let Authorized = RenderAuthorized(getAuthority()); // eslint-disable-line

  继续跟踪上述代码,可以看到../components/Authorized中有两个export:1、当前权限值,通过renderAuthorize方法传入当前权限值计算(对应let Authorized = RenderAuthorized(getAuthority()));2、Authorized组件,有三部分组成,其中有我们的
AuthorizedRoute组件。

//../components/Authorized
import AuthorizedRoute from './AuthorizedRoute';
....
Authorized.Secured = Secured;
Authorized.AuthorizedRoute = AuthorizedRoute;
Authorized.check = check;


....


const renderAuthorize = currentAuthority => {
  if (currentAuthority) {
    if (currentAuthority.constructor.name === 'Function') {
      CURRENT = currentAuthority();
    }
    if (currentAuthority.constructor.name === 'String') {
      CURRENT = currentAuthority;
    }
  } else {
    CURRENT = 'NULL';
  }
  return Authorized;
};


export { CURRENT };
export default renderAuthorize;

  通过一些类引用,终于看到了最终的AuthorizedRoute。

//AuthorizedRoute.js
....
return (
      <Authorized
        authority={authority}
        noMatch={<Route {...rest} render={() => <Redirect to={{ pathname: redirectPath }} />} />}
      >
        <Route {...rest} render={props => (Component ? <Component {...props} /> : render(props))} />
      </Authorized>
    );

在AuthorizedRoute组件中又包含Authorized组件封装。Authorized是一个高阶组件,通过调用CheckPermissions方法返回一个新的组件。具体的Authorized代码如下:

import CheckPermissions from './CheckPermissions';


render() {
    const { children, authority, noMatch = null } = this.props;
    const childrenRender = typeof children === 'undefined' ? null : children;
    return CheckPermissions(authority, childrenRender, noMatch);
 }

  CheckPermissions组件(返回有check,引用时被重命名为 CheckPermissions),其中CURRENT即为之前通过RenderAuthorized(getAuthority())时,计算的当前权限。checkPermissions方法,会判定CURRENT是否在authority权限范围内,如果有权限则返回target,否则返回Exception

import { CURRENT } from './index';
...


/**
 * 通用权限检查方法
 * Common check permissions method
 * @param { 权限判定 Permission judgment type string |array | Promise | Function } authority
 * @param { 你的权限 Your permission description  type:string} currentAuthority
 * @param { 通过的组件 Passing components } target
 * @param { 未通过的组件 no pass components } Exception
 */
const checkPermissions = (authority, currentAuthority, target, Exception) => {
    ...
})


...


const check = (authority, target, Exception) => {
  return checkPermissions(authority, CURRENT, target, Exception);
};


export default check;

  至此可知。结合路由生成是调用AuthorizedRoute组件封装和AuthorizedRoute组件的功能

  • 路由生成:
<Switch>
  {redirectData.map(item => (
    <Redirect key={item.from} exact from={item.from} to={item.to} />
  ))}
  {getRoutes(match.path, routerData).map(item => (
    <AuthorizedRoute
      key={item.key}
      path={item.path}
      component={item.component}
      exact={item.exact}
      authority={item.authority}
      redirectPath="/exception/403"
    />
  ))}
  <Redirect exact from="/" to={bashRedirect} />
  <Route render={NotFound} />
</Switch>
  • AuthorizedRoute
<Authorized
    authority={authority}
    noMatch={<Route {...rest} render={() => <Redirect to={{ pathname: redirectPath }} />} />}
  >
    <Route {...rest} render={props => (Component ? <Component {...props} /> : render(props))} />
  </Authorized>

  当 authority={item.authority}权限通过的时候,及生成路由组件Route,该路由对应的组件为component={item.component};当权限不通过时,即加载nomatch生成的组件Route,此时重定向到redirectPath=”/exception/403”。

猜你喜欢

转载自blog.csdn.net/zcs425171513/article/details/80681110