url 的hash和 HTML5 的history

   前言

 对于 Vue 这类渐进式前端开发框架,为了构建 SPA(单页面应用),需要引入前端路由,这也就是 Vue-Router 存在的意义。vue 的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。传统的页面应用是用一些超链接来实现页面切换和跳转的。在vue-router单页面应用中,则是路径之间的切换,实际上就是组件的切换。

 前端路由的核心 —— 改变视图的同时不会向后端发出请求

 为了达到这一目的,vue-router 的 mode 提供两种模式:hash 、history。默认为 hash 模式,可以用如下方式进行修改成 history 模式:

  

 

  hash 和 history 的区别

  • URL 的 hash —— 即地址栏 URL 中会出现 # 哈希符号(锚点)。

  比如这个 URL:http://www.abc.com/#/hello,hash 的值为 #/hello。

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

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

  它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。

 

  • HTML5 的 history —— 利用了 HTML5 History Interface 中新增的 pushState() replaceState() 方法。(需要特定浏览器支持)

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

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

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

  不过这种模式还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,就需要前端自己配置404页面。

   pushState() 和 replaceState() 这两个神器的作用就是可以将url替换并且不刷新页面,http并没有去请求服务器该路径下的资源,但是一旦刷新就会暴露这个实际不存在的,显示404(因为浏览器一旦刷新,就是去真正请求服务器资源)

  那么如何去解决history模式下刷新报404的弊端呢,这就需要服务器端做点手脚,将不存在的路径请求重定向到入口文件(index.html),前后端联手。

因此可以说,hash 模式和 history 模式都属于浏览器自身的特性,Vue-Router 只是利用了这两个特性(通过调用浏览器提供的接口)来实现前端路由.

 

  总结

 一般情况下,hash 和 history 都可以,除非你更在意颜值,#符号夹杂在 url 里看起来确实不太美丽。

 如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成URL 跳转而无须重新加载页面。

 另外,根据 Mozilla Develop Network 的介绍,调用 history.pushState() 相比于直接修改 hash,存在以下优势:

  • pushState() 设置的新 URL 可以是与当前 URL 同源的任意 URL;而 hash 只可修改 # 后面的部分,因此只能设置与当前 URL 同文档的 URL;
  • pushState() 设置的新 URL 可以与当前 URL 一模一样,这样也会把记录添加到栈中;而 hash 设置的新值必须与原来不一样才会触发动作将记录添加到栈中;
  • pushState() 通过 stateObject 参数可以添加任意类型的数据到记录中;而 hash 只可添加短字符串;
  • pushState() 可额外设置 title 属性供后续使用。

 当然啦,history 也不是样样都好。通过history api,我们丢掉了丑陋的#,但是它也有个问题:不怕前进,不怕后退,就怕刷新f5,(如果后端没有准备的话),因为刷新是实实在在地去请求服务器的,不玩虚的。 在hash模式下,前端路由修改的是#中的信息,而浏览器请求时是不带它玩的,所以没有问题.但是在history下,你可以自由的修改path,当刷新时,如果服务器中没有相应的响应或者资源,会分分钟刷出一个404来。




参考资料:https://www.jb51.net/article/144341.htm
 
 
 

 

posted @ 2021-11-17 16:07  打遍天下吴敌手  阅读(199)  评论(0)    收藏  举报