react-router-v6原理解析 - branch的积分规则

147 阅读1分钟

积分规则

  • flattenRoutes 中会拍平路由结构的过程中 , 会形成一个一个的branch , 而每一个branch会通过 computeScore得到一个score. 这个score会影响后续matchRouteBranch的匹配结果.

computeScore

  • dynamicSegmentValue: 动态参数 记3分
<Route path="/user/:id" element={<Detail />}>
  • indexRouteValue: 索引路由 记2分
<Route index element={<Home />} />
  • emptySegmentValue: 空 segment 记1分
<Route path="/user/info/" element={<Detail />} />
  • staticSegmentValue: 字符串 segment 记10分
// 即user和info 
<Route path="/user/info" element={<Detail />} />
  • splatPenalty: * 记 -2分
<Route path="*" element={<NoMatch />} />
一个🌰
      <Routes>
          <Route index element={<Home />} />
          <Route path="/" element={<About />} />
          <Route path=":id" element={<Dashboard />} />
          <Route path="*" element={<NoMatch />} />
      </Routes>
  • 第一个含有index的branch的得分为6
  1. 第一个 2 对应两个 segments(这里得到的两个'')
  2. 第二个 2 对应 index
  3. 第三个 2 对应两个 emptySegmentValue
const score = 2 + 2 + 2
  • 第二个 branch的得分同上, 不过少了 index 所以得分为 4
const score = 2 + 2
  • 第三个branch 的得分为 5
  1. 第一个 2 对应两个 segments(一个''和:id)
  2. 第二个 3 对应 dynamicSegmentValue
  3. 第三个 1 对应一个 emptySegmentValue
const score = 2 + 3 + 1
  • 第四个branch的得分为 3
  1. 第一个 2 对应两个 segments(一个''和*)
  2. 第二个 -2 对应 *
  3. 第三个 1 对应 一个emptySegmentValue
const score = 2 - 2 + 1
具体源码和注释
const paramRe = /^:\w+$/;// 动态参数匹配的正则
const dynamicSegmentValue = 3; // 动态参数计3分
const indexRouteValue = 2; // 索引路由记2分 
const emptySegmentValue = 1; // 空串则记1分(什么时候会出现空字符串)
const staticSegmentValue = 10; // 存字符串则记10分
const splatPenalty = -2; // *记-2分
const isSplat = (s: string) => s === "*";

function computeScore(path: string, index: boolean | undefined): number {
  let segments = path.split("/"); // 以 / 作为分隔符得到 segments
  let initialScore = segments.length; // 以 segments的数量作为初始分数
  if (segments.some(isSplat)) {
    // 如果 path中存在 * , 则 -2
    initialScore += splatPenalty;
  }

  if (index) {
    // index , 则+2
    initialScore += indexRouteValue;
  }

  return segments
    .filter((s) => !isSplat(s)) // 过滤掉 *
    .reduce(
      (score, segment) =>
        score +
        (paramRe.test(segment)
          ? dynamicSegmentValue
          : segment === ""
          ? emptySegmentValue
          : staticSegmentValue),
      initialScore
    );
}