深入理解前端中的 hash 和 history 路由

我们在使用 Vue 或者 React 等前端渲染时,通常会有 hash 路由和 history 路由两种路由方式。

  1. hash 路由:监听 url 中 hash 的变化,然后渲染不同的内容,这种路由不向服务器发送请求,不需要服务端的支持;
  2. history 路由:监听 url 中的路径变化,需要客户端和服务端共同的支持;

我们一步步实现这两种路由,来深入理解下底层的实现原理。我们主要实现以下几个简单的功能:

  1. 监听路由的变化,当路由发生变化时,可以作出动作;
  2. 可以前进或者后退;
  3. 可以配置路由;

hash 路由

在 Hash 模式下,URL 中的 hash 值(即 # 号后面的部分)会被用来表示当前页面的状态,而不会引起页面的刷新。因此,使用 hash 模式可以实现无需后端支持即可进行前端路由。

例如,如果我们访问 http://example.com/#/home,则会渲染出 Home 组件,而不会刷新整个页面。如果我们点击链接切换到 http://example.com/#/about,则会渲染出 About 组件,同样不会刷新整个页面。

在 hash 模式下,Vue Router 会监听 URL 中 hash 值的变化,当 hash 值发生变化时,会自动匹配对应的路由并渲染对应的组件。

 

JS使用hash跳转到url-alan路由

location.hash="url-alan"

 

当页面中的 hash 发生变化时,会触发hashchange事件,因此我们可以监听这个事件,来判断路由是否发生了变化。

window.addEventListener(
    'hashchange',
    function (event) {
        const oldURL = event.oldURL; // 上一个URL
        const newURL = event.newURL; // 当前的URL
        console.log(newURL, oldURL);
    },
    false
);

 

history 路由

在 History 模式下,URL 中的路径会被用来表示当前页面的状态,而不再需要用 hash 值。使用 History 模式需要后端服务器的支持,因为在刷新页面时,需要向服务器发送请求获取对应的 HTML 页面。

例如,如果我们访问 http://example.com/home,则会渲染出 Home 组件,如果我们点击链接切换到 http://example.com/about,则会渲染出 About 组件,同样不会刷新整个页面。

在 History 模式下,Vue Router 会监听 URL 中路径的变化,当路径发生变化时,会自动匹配对应的路由并渲染对应的组件。

 

JS使用history跳转到url-alan路由

// history.pushState(state, title, url)
window.history.pushState({},'title','url-alan')

 

在 history 路由中,我们一定会使用window.history中的方法,常见的操作有:

  • back():后退到上一个路由;
  • forward():前进到下一个路由,如果有的话;
  • go(number):进入到任意一个路由,正数为前进,负数为后退;
  • pushState(obj, title, url):前进到指定的 URL,不刷新页面;
  • replaceState(obj, title, url):用 url 替换当前的路由,不刷新页面;

调用这几种方式时,都会只是修改了当前页面的 URL,页面的内容没有任何的变化。但前 3 个方法只是路由历史记录的前进或者后退,无法跳转到指定的 URL;而pushStatereplaceState可以跳转到指定的 URL。如果有面试官问起这个问题“如何仅修改页面的 URL,而不发送请求”,那么答案就是这 5 种方法。

如果服务端没有新更新的 url 时,一刷新浏览器就会报错,因为刷新浏览器后,是真实地向服务器发送了一个 http 的网页请求。因此若要使用 history 路由,需要服务端的支持。

应用的场景

pushState 和 replaceState 两个方法跟 location.href 和 location.replace 两个方法有什么区别呢?应用的场景有哪些呢?

  1. location.href 和 location.replace 切换时要向服务器发送请求,而 pushState 和 replace 仅修改 url,除非主动发起请求;
  2. 仅切换 url 而不发送请求的特性,可以在前端渲染中使用,例如首页是服务端渲染,二级页面采用前端渲染;
  3. 可以添加路由切换的动画;
  4. 在浏览器中使用类似抖音的这种场景时,用户滑动切换视频时,可以静默修改对应的 URL,当用户刷新页面时,还能停留在当前视频。

 

如何选择hash和history

总的来说,Hash 模式适合开发纯前端应用,不需要服务器的支持,但是 URL 比较丑陋。History 模式适合开发需要 SEO 支持的应用,但是需要服务器的支持,并且需要进行 URL 重写以去除 URL 中的 # 号。
 
如果你不需要考虑 SEO 问题,或者你的服务器配置不允许 URL 重写,那么可以选择使用 hash 模式;
如果你需要考虑 SEO 问题,或者你的服务器支持 URL 重写,那么可以选择使用 history 模式。

 

如何判断网页路由是hash还是history模式 

  1. 观察URL中的#符号。如果URL中含有#符号,那么就是hash路由;如果没有#符号,那么就是history路由。
  2. 在JavaScript中使用location对象来判断。可以通过检查location对象的hash属性来确定当前URL是否包含#符号,如果包含#符号,则使用了hash路由。如果没有#符号,则使用了history路由。

例如,以下代码可以检查当前页面是否使用了hash路由:

if (window.location.hash) {
  // 使用了hash路由
} else {
  // 使用了history路由
}

另外,如果网站使用了前端框架(如React、Vue等),则可能需要查看该框架的路由实现方式来确定当前页面使用了哪种路由方式。

 

 

参考网址

posted @ 2023-02-04 23:41  泠风lj  阅读(1256)  评论(0编辑  收藏  举报