07-开始构建Router组件
7.2.3 开始构建 组件
为了在Router组件上开始工作,你需要再次了解创建组件的基础知识。尽管你应该对此很熟悉了,但最终你会构建一个做至此从没见过的独特事情的组件。好消息是不需要施展任何“魔法”就能创建路由器。我们将使用React组件,向Router组件中添加一些逻辑,然后将其用作应用程序渲染的主要组件。
这也许看起来没什么大不了的。你也许在想:“好吧,所以它是一个组件。毕竟这是React,所以看起来……很正常?”我之所以要指出这一点,是因为这是一个强大而灵活的东西的好例子——使用者“仅”用React就能做到但却不会立即想到。我们不需要任何全新的工具,只需要找到一种记录URL与组件映射关系的方法以及一种与正确浏览器API交互的方法。现在可以开始构建这个组件了。
React Router如何
如果曾经使用过React,也许听说过 React Router 。它是开源里最流行的React项目之一并且是迄今为止React应用程序最流行的路由解决方案。你也许想知道为什么不直接安装 React Router 并学习如何使用它的API。虽然可以那样做,但我认为这样你就错过了一个了解如何使用React组件做一些原本可能没有意识到React可以做的事情(如将URL映射到组件)的机会。比起通过用npm简单地安装一些东西所学到的,通过自己构建一些东西可以学到更多。
现在,这与你在商业环境或任何类型的生产环境中可能做的事情不同。如同从头构建自己的路由器一样有帮助,作为工程师的主要任务(几乎总是)是为公司交付价值,要最高效地实现这一点,要么构建工具,要么使用经过良好测试的、性能卓越而且简单易用的工具。
认识到这一点,你和你的团队也许就会选择使用 React Router 而不是构建自己的路由器。选择一款维护良好的、流行的、符合需求的开源库通常是一个更好的工程和商业决策。当第12章讨论服务器端渲染时,我们会用 React Router 替换掉自己构建工具的路由,以便能利用 React Router 的一些特性。
代码清单7-3展示了如何搭建Router组件。这里除了在组件上设置 routes 属性没有什么不寻常的东西。注意,因为不想做任何事情来动态改变路由,所以不能将路由存储在React的本地组件状态中。某些情况下可能想在运行时动态改变路由,如用户主动定制应用程序或类似的事情。在这些情况下可以使用组件的 state 接口。不过这里不会有这种需要,所以将路由放在组件上即可。
代码清单7-3 搭建Router组件(src/components/router/Router.js)
export default class Router extends Component {
static propTypes = { ⇽--- 指定PropTypes——router会接收children和location来工作
children: PropTypes.object,
location: PropTypes.string.isRequired
};
constructor(props) {
super(props);
this.routes = {}; ⇽--- 在Router组件上用一个对象来存储路由信息
}
render() {} ⇽--- Router组件会有一个render方法
}
现在有了Router组件的基本骨架,可以开始添加一些之后组件核心方法会用到的辅助方法。
要使用路由还有一些事情需要做。如果仔细看过代码清单7-2,你也许会看到传入的 path 属性并不全是以 / 开头的。这看上去似乎是一件小事,但需要确保路由器的使用者能够这样做。如果使用者由于偶然或路由嵌套而包含太多斜杠,还需要确保任何双斜杠( // )都已被删除。
让我们看看如何创建两个辅助方法来解决这些问题。首先,我们想要创建一个实用方法来清理路径。我们将使用一个简单的正则表达式将任何双斜线替换为单斜杠。如果不熟悉正则表达式,可以从网上找到很多不错的资源来进一步学习。正则表达式是文本模式匹配的有效方式,也是很多软件开发形式的关键,但它们可能也显得非常晦涩,难以理解或者学习。幸好,我们只需要用一个简单的正则表达式来查找并替换所有双斜杠( // )。代码清单7-4展示了如何实现简单的 cleanPath 方法。注意,使用正则表达式清理字符串可能比较棘手,所以不要期望遇到的每种情况都如此简单。
代码清单7-4 将cleanPath实用方法添加到Router组件中(src/components/router/Router.js)
//...
cleanPath(path) {
return path.replace(/\/\//g, '/'); ⇽--- cleanPath使用String.replace从path属性(/)中移除所有双斜杠字符
}
//...
我们不会深入讨论正则表达式,但我们至少应该注意一些事情。首先,JavaScript的正则表达式的基本语法是两个斜杠和中间的表达式 /<regular expression>/ 。其次,即使\ /\/ 这样的字符串看起来很神秘并且有点儿像W,它也只是添加了转义字符( \ )的两个斜杠( // ),因此它们不会被解释为注释或者其他东西。最后,添加到正则表达式末尾的 g 字符是一个意味着匹配所有出现的标记。想学习更多关于正则表达式的内容,可以了解一下正则表达式的各部分的详细信息并练习匹配不同模式。
现在可以清除 // 了,我们需要为新添加的路由处理一些其他情况。我们将调用 normalize- Route 这个实用方法,它会确保父路由和子路由创建为正确的字符串并在必要时添加斜杠。该函数会接收一个路径和一个可选的父路由。有了这两个输入就可以应付一些情况。代码清单7-5展示了 normalizeRoute 方法的工作原理。
代码清单7-5 创建normalizeRoute实用方法(src/components/router/Router.js)
//...
normalizeRoute(path, parent) { ⇽--- 函数接收路径和父路由对象——路由属性是一个路径字符串
if (path[0] === '/') { ⇽--- 如果路径只是一个/,可以直接返回它——我们不需要把它与父路由连接在一起
return path;
}
if (parent == null) { ⇽--- 如果没有被提供父路由,可以直接返回路径,因为没有什么要连接的
return path;
}
return `${parent.route}/${path}`; ⇽--- 如果有父路由,通过连接将路径加入父路由的路径中
}
//...