前端路由实现

相关问题

  • 路由是什么
  • 前端路由的实现方式和实现原理
  • 前端路由和服务端路由的区别
  • 前端路由的优势
  • 前端路由的不足

回答关键点

路由 Hash 路由 History 路由 无刷新 SPA(Single-page application,单页面 Web 应用)

路由(routing)就是通过互联的网络把信息从源地址传输到目的地址的活动。 —— 维基百科

对于 Web 开发来说,路由的实质是 URL 到对应的处理程序的映射。

Web 路由既可以由服务端,也可以由前端实现。其中前端路由根据实现方式的不同,可以分为 Hash 路由History 路由

前端路由对于服务端路由来说,最显著的特点是页面可以在无刷新的情况下进行页面的切换。基于前端路由的这一特点,诞生了一种无刷新的单页应用开发模式 SPA。SPA 通过前端路由避免了页面的切换打断用户体验,让 Web 应用的体验更接近一个桌面应用程序。

知识点深入

前端路由根据具体实现方式的不同,可以分为 Hash 路由History 路由 两种,这两种实现方式各有其优势和局限性。

1. Hash 路由

一个 URI 的组成如下所示。其中的 fragment 部分就是 Hash 路由所读取的内容。

     foo://example.com:8042/over/there?name=ferret#nose     \_/   \______________/\_________/ \_________/ \__/      |           |            |            |        |   scheme     authority       path        query   fragment      |   _____________________|__     / \ /                        \     urn:example:animal:ferret:nose

Copy

fragment 本质是用来标识次级资源,fragment 有以下特点:

  • 修改 fragment 的内容不会触发网页重载。
  • 修改 fragment 的内容会改变浏览器的历史记录。
  • 修改 fragment 的内容会触发浏览器的 onhashchange 事件。

基于 fragment 的以上特点,可实现基于 Hash 的前端路由。

1.1 实现原理

我们可以通过监听 hashchange 事件来监听页面 hash 的变化,通过解析 hash 的值来切换页面。示例如下:

/**  
 * 解析 hash * @param hash * @returns */function parseHash (hash) {  
    // 去除 # 号    hash = hash.replace(/^#/, '');  
    // 简单解析示例    const parsed = hash.split('?');  
    // 返回 hash 的 path 和 query    return {        pathname: parsed[0],        search: parsed[1]    }}  
  
/**  
 * 监听 hash 变化 * @returns */function onHashChange () {  
    // 解析 hash    const { pathname, search } = parseHash(location.hash);  
    // 切换页面内容    switch (pathname) {        case '/home':            document.body.innerHTML = `Hello ${search}`;            return;        default:            return;    }}  
  
window.addEventListener('hashchange', onHashChange);  

Copy

1.2 优缺点

Hash 路由由于通过监听 hash 变化实现,所以有以下优势和不足:

优点

  1. 兼容性最佳。
  2. 无需服务端配置。

缺点

  1. 服务端无法获取 hash 部分内容。
  2. 可能和锚点功能冲突。
  3. SEO 不友好。

2. History 路由

Hash 路由是一个相对“Hack”的方式,利用了 fragment 来实现路由功能。而 History 路由则是通过浏览器原生提供的操作 History 的能力来实现的路由功能。

2.1 实现原理

History 路由核心主要依赖 History API 里的两个方法和一个事件,其中两个方法用于操作浏览器的历史记录,事件用于监听历史记录的切换:

方法

  • history.pushState:将给定的 Data 添加到当前标签页的历史记录栈中。
  • history.replaceState:将给定的 Data 更新到历史记录栈中最新的一条记录中。

事件

  • popstate:监听历史记录的变化。

通过以上 API 即可实现一个前端路由,示例如下:

/**  
 * 监听 history 变化 * @returns */function onHistoryChange () {  
    // 解析 location    const { pathname, search } = location;  
    // 根据页面不同执行不同内容    switch (pathname) {        case '/home':            document.body.innerHTML = `Hello ${search.replace(/^\?/, '')}`;            return;        default:            document.body.innerHTML = `Hello World`;            return;    }}  
  
/**  
 * 页面跳转 * @returns */function pushState (target) {  
    history.pushState(null, '', target);    onHistoryChange();}  
  
// 3 秒后路由跳转  
setTimeout(() => {  
    pushState('/home?name=HZFEStudio');}, 3000);  
  
// 6 秒后返回  
setTimeout(() => {  
    history.back();}, 6000);  
  
window.addEventListener('popstate', onHistoryChange);  

Copy

2.2 优缺点

History 路由由于通过 History API 实现,所以有以下优势和不足:

优点

  1. 服务端可获取完整的链接和参数。
  2. 前端监控友好。
  3. SEO 相对 Hash 路由友好。

缺点

  1. 兼容性稍弱。
  2. 需要服务端额外配置(各 path 均指向同一个 HTML)。

3. 前端路由的优缺点

前端路由是前后端分离的开发模式的产物,对比服务端路由,前端路由的实现方式有以下优势和不足:

优点

  1. 无刷新切换内容,用户体验更佳。
  2. 减轻服务端压力。

缺点

  1. 初次加载耗时长。
  2. SEO 效果不佳。

参考资料

  1. Window: hashchange event
来自:浏览器 | 剑指前端