关于hash和history路由那些事

268 阅读3分钟

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战

hash 模式

早期的前端路由是基于 location.hash 来实现的,原理其实很简单,location.hash 的是就是 URL 后面#号的值,如下:

https:// blog.codedogs.top#index

前面这个网址的 location.hash 就是#index

hash 路由模式的实现主要是基于以下几个特性:

  • URL 中的 hash 值只是客户端的一种状态,也就是说向服务器发送请求时,hash 部分不会发送到服务器
  • hash 值的改变,都会在浏览器的访问历史中增加一个记录,因此可以前进后退控制访问记录
  • 可以通过 a 标签,并且设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用 JavaScript 来对 location.hash 进行赋值,改变 URL 的 hash 值
  • 我们可以使用 haschange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)

history 模式

HTML5 提供了 History API 来实现 URL 的变化,其中主要的 API 有以下两个: history.pushState() 和 history.repalseState(),这两个 API 可以在不进行刷新的情况下,操作浏览器的历史记录,唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示:

window.history.pushState(null,null,path)
window.history.replaceState(null,null,path)

history 路由模式的实现主要基于存在以下几个特性

  • pushState 和 replaceState 两个 API 来操作实现 URL 的变化
  • 我们可以使用 popstate 事件来监听 URL 的变化,从而对页面进行跳转(渲染)
  • history.pushState() 或 history,resplaceState()不会触发 popstate 事件,这时候我们需要手动触发页面跳转(渲染)

history 的问题

History 的路由模式虽然好看,但是还需要后台的配置,因为前台是单页面应用,后台没有正确的配置就是会返回 404 了

所以,在服务端需要增加一个覆盖所有情况的候选资源,如果 URL 匹配不到任何静态资源,则应该返回 index.html 页面,这个页面就是 app 的依赖页面。

简单实现 vue Routher

Vue Router 核心是,通过 Vue.use 注册插件,在插件的 install 方法中获取用户设置的 router 对象,当前浏览器对象发生变化时,根据 router 对象匹配相应的路由,获取组件,并将该组件渲染到视图上。

  1. 如何在 install 方法获取 Vue 实例上的 router 属性

可以利用 Vue.mixin 混入生命周期函数 beforeCreate,在 beforeCreate 函数中可以获取到 Vue 实例上的属性并赋值到 Vue 原型链上。

_Vue.mixin({
   if(this.$options.router){
     _Vue.prototype.$router = this.$options.router
}
})
  1. 如何触发更新

hash 模式下:

  • 通过 localtion.hash 修改 hash 的值,触发更新
  • 通过监听 haschange 事件监听浏览器前进后退,触发更新

history 模式下:

  • 通过 history.pushState 修改浏览器地址触发更新
  • 通过监听 popState 事件监听浏览器前进或者后退,触发更新

如何渲染 router-view 组件?

  • 通过 Vue.observable 在 router 实例上创建一个保存当前路由的监控对象 current;
  • 当浏览器地址变化时,修改监控 current
  • 在 router-view 组件中监听监控对象 current 的变化,当 current 变化后,获取用户注册的 component,并利用 h 函数将 component 渲染 vnodes,进而更新页面视图