从 React Router 谈谈路由的那些事

发表于 5年以前  | 总阅读数:1240 次

React Router 是专为 React 设计的路由解决方案,在使用 React 来开发 SPA (单页应用)项目时,都会需要路由功能,而 React Router 应该是目前使用率最高的。

React Router 并不是 Facebook 的 React 官方团队开发的,但是据说有官方人员参与开发。React Router 的设计思想来源于 Ember 的路由,如果原来有用过 Ember 的路由,那么应该对 React Router 不会陌生。

什么是路由?

对于没有开发过后端,也没有开发过 SPA 的前端来说,「路由」这个名词可能会让人比较困惑,这里的路由并不是指「硬件路由」,也不是网络七层协议中的「网络层路由」,但是其思想原理是一样的。我尽量简单通俗的介绍一下。

假如我们有一台提供 Web 服务的服务器的网络地址是:10.0.0.1,而该 Web 服务又提供了三个可供用户访问的页面,其页面 URI 分别是:

http://10.0.0.1/
    http://10.0.0.1/about
    http://10.0.0.1/concat 

那么其路径就分别是 //about/concat

当用户使用 http://10.0.0.1/about 来访问该页面时,Web 服务会接收到这个请求,然后会解析 URI 中的路径 /about,在 Web 服务的程序中,该路径对应着相应的处理逻辑,程序会把请求交给路径所对应的处理逻辑,这样就完成了一次「路由分发」,这个分发就是通过「路由」来完成的。

前端路由

前端的路由和后端的路由在实现技术上不一样,但是原理都是一样的。在 HTML5 的 history API 出现之前,前端的路由都是通过 hash 来实现的,hash 能兼容低版本的浏览器。如果我们把上面例子中提到的 3 个页面用 hash 来实现的话,它的 URI 规则中需要带上 #

http://10.0.0.1/
    http://10.0.0.1/#/about
    http://10.0.0.1/#/concat 

Web 服务并不会解析 hash,也就是说 # 后的内容 Web 服务都会自动忽略,但是 JavaScript 是可以通过 window.location.hash 读取到的,读取到路径加以解析之后就可以响应不同路径的逻辑处理。

history 是 HTML5 才有的新 API,可以用来操作浏览器的 session history (会话历史)。基于 history 来实现的路由可以和最初的例子中提到的路径规则一样。

http://10.0.0.1/
    http://10.0.0.1/about
    http://10.0.0.1/concat 

用户可能都察觉不到该访问地址是 Web 服务实现的路由还是前端实现的路由。

从性能和用户体验的层面来比较的话,后端路由每次访问一个新页面的时候都要向服务器发送请求,然后服务器再响应请求,这个过程肯定会有延迟。而前端路由在访问一个新页面的时候仅仅是变换了一下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。

说了这么多的「路由基础」,该回头来说说 React Router 了。

配置路由

使用 React Router 来配置上面例子中的三个页面,每个页面分别对应着一个 React Component。

/about 页面的入口文件 about.js

import React from 'react';

    class About extends React.Component {
        render () {
            return (
                <h3>This is About page.</h3>
            );
        }
    };

    export default About;

/concat 页面的入口文件 concat.js

import React from 'react';

    const Concat = () => {
        return (
            <h3>This is Concat page.</h3>
        );
    };

    export default Concat;

/ 首页对应的是 app.js,它也是整个 React Component 的入口文件。

import React from 'react';
    import {Link} from 'react-router';

    class App extends React.Component {
        render () {
            return (
                <div>
                    <h1>React Router Demo</h1>
                    <hr />
                    <p>
                        by <a href="http://stylechen.com/" target="_blank">stylechen.com</a>
                    </p>
                    <ul>
                        <li><Link to="/">Home</Link></li>
                        <li><Link to="/about">About</Link></li>
                        <li><Link to="/concat">Concat</Link></li>
                    </ul>
                    {this.props.children}
                </div>
            )
        }
    };

    export default App;

app.js 中的 Link 组件是 React Router 提供的组件,用于链接到相应页面。如果直接使用 a 标签的话相当于页面跳转了,而使用 Link 只是应用内的路由跳转,页面跳转意味着先重新加载整个页面,然后才是应用内部的路由跳转。

index.js 中包含了 route 的配置,同时在该文件中对 React Component 进行 render

import React from 'react';
    import ReactDOM from 'react-dom';

    import App from './component/app';
    import About from './component/about';
    import Concat from './component/concat';

    import {Router, Route, browserHistory} from 'react-router';

    const router = (
        <Router history={browserHistory}>
            <Route path="/" component={App}>
                <Route path="about" component={About} />
                <Route path="concat" component={Concat} />
            </Route>
        </Router>
    );

    ReactDOM.render(
        router,
        document.getElementById('root')
    );

Route 组件就是用于配置路由,path 属性用于配置路径,component 就是对应的 React Component。

Route 组件支持嵌套,嵌套时子组件的路径可以继承父组件的路径,上面的 about 嵌套后就成了 /about,当然也可以直接以根路径为开头。

此时再看看 app.js 中的 this.props.childrenAboutConcat 两个页面组件其实就是以这种形式插入到父组件中,只是插入的时候用 React Router 提供的组件再包装了一下使它们可以支持路由。

Router组件还有一个重要的属性,那就是history,这可以配置使用history来实现路由,如果没有配置这个属性则默认使用hash

路由参数

假如我们有很多 list 页面,这些页面除了动态内容不同,其他的页面部分都相同,这个时候需要怎么配置路由和组件呢?

这种场景就需要用到路由的参数功能,增加一条包含参数的路由配置。

import List from './component/list';

    <Route path="list/:id" component={List} />

注意 path 属性中的 :id 就是该路由的参数(param)。再来看看 List 页面的组件。

/list 对应了 list.js

import React from 'react';

    class List extends React.Component {
        render () {
            return (
                <div>
                    <h3>This is List page.</h3>
                    <p>The list page id is&nbsp;
                        <b style={{color: 'red'}}>{this.props.params.id}</b>
                    </p>
                </div>
            );
        }
    };

    export default List;

List 组件中,可以直接通过 this.props.params.id 来访问实际的参数值(这里的id key 就和定义路径的 :id 相对应),React Router 将路由的数据都通过 props 传递给了页面组件,这样就可以非常方便的访问路由相关的数据了。

组件的生命周期

每个 React Component 都有生命周期,按照常规的策略,当调用父组件的 render 的时候,会将所有的页面子组件也进行 render,这种逻辑显然不合理了。那么当一个 React 的应用有了路由功能后,它的生命周期会如何处理呢?

当切换路由的路径的时候才去 render 对应的页面组件,给 About 绑定两个组件装载和卸载的事件,就可以测试出来了。

import React from 'react';

    class About extends React.Component {
        componentDidMount () {
            console.log('mount');
        }

        componentWillUnmount () {
            console.log('un mount');
        }

        render () {
            return (
                <h3>This is About page.</h3>
            );
        }
    };

    export default About;

在切换到 /about 页面的时候,会打印出 mount,而当离开页面的时候会打印出 un mount。路由的这种进入时装载组件离开时卸载组件的策略就可以做到合理利用「资源」,不会一下把所有的组件都装载进来使内存占用飙升,也不会离开时没有卸载而时内存泄漏。

React Router 还有很多比较方便 API,这里不一一列举,通过上面的文章基本能覆盖到常规的使用场景了,想了解更多使用方面查看 项目主页。

本文的 demo 代码都已经托管在 github 上了,可以自己下载到本地浏览。

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:7月以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:7月以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:7月以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:7月以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:7月以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:7月以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:7月以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:7月以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:7月以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:7月以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:7月以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:7月以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:7月以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:7月以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:7月以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:7月以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:7月以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:7月以前  |  398次阅读  |  详细内容 »
 相关文章
为Electron程序添加运行时日志 4年以前  |  19528次阅读
Node.js下通过配置host访问URL 5年以前  |  5614次阅读
用 esbuild 让你的构建压缩性能翻倍 3年以前  |  5333次阅读
 目录