vue路由原理

路由模式

vue-router在实现单页面前端路由时,提供了三种方式:Hash模式、History模式、abstract模式,根据mode参数来决定采用哪一种方式

  • hash: 使用 URL hash 值来作路由,默认模式
  • history: 依赖 HTML5 History API 和服务器配置,查看 HTML5 History 模式
  • abstract: 支持所有 JavaScript 运行环境,如node服务器端

Hash模式

vue-router 默认模式是 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,当 URL 改变时,页面不会去重新加载

 

hash(#)是URL 的锚点,代表的是网页中的一个位置,单单改变#后的部分(/#/..),浏览器只会加载相应位置的内容,不会重新加载网页,也就是说 #是用来指导浏览器动作的,对服务器端完全无用,HTTP请求中不包括#;同时每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用”后退”按钮,就可以回到上一个位置;所以说Hash模式通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据

 

History模式

 

HTML5 History API提供了一种功能,能让开发人员在不刷新整个页面的情况下修改站点的URL,就是利用 history.pushState API 来完成 URL 跳转而无须重新加载页面

 

由于hash模式会在url中自带#,如果不想要很丑的 hash,我们可以用路由的 history 模式,只需要在配置路由规则时,加入"mode: 'history'",这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面

abstract模式

 

abstract模式是使用一个不依赖于浏览器的浏览历史虚拟管理后端。

 

根据平台差异可以看出,在 Weex 环境中只支持使用 abstract 模式。 不过,vue-router 自身会对环境做校验,如果发现没有浏览器的 API,vue-router 会自动强制进入 abstract 模式,所以 在使用 vue-router 时只要不写 mode 配置即可,默认会在浏览器环境中使用 hash 模式,在移动端原生环境中使用 abstract 模式(也可以明确指定在所有情况下都使用 abstract 模式)

 

 

前端路由的两种实现方法

1.hash路由

class Routers {
  constructor() {
     // 以键值对的形式储存路由
     this.routes = {}

     // 当前路由的URL

     this.currentUrl = ''
     // 记录出现过的hash
     this.history = []
     // 作为指针,默认指向this.history的末尾,根据后退前进指向history中不同的hash
     this.currentIndex = this.history.length - 1
     // 默认不是后退操作
     this.isBack = false

     this.refresh = this.refresh.bind(this)
     this.goBack = this.goBack.bind(this)
     // 监听事件
     window.addEventListener('load', this.refresh, false)
     window.addEventListener('hashchange', this.refresh, false)
}

    // 将path路径与对应的callback函数储存
   route(path, callback = () => {}) {
       this.routes[path] = callback
    }

   // 回退
   goBack() {
       this.isBack = true
       this.currentIndex <= 0
         ? (this.currentIndex = 0)
         : (this.currentIndex = this.currentIndex - 1)
        location.hash = `#${this.history[this.currentIndex]}`
        this.routes[this.history[this.currentIndex]]()
   }

    // 刷新
   refresh() {
        // 获取当前URL中的hash路径
       this.currentUrl = window.location.hash.slice(1) || '/'
      if (!this.isBack) {
          // 如果不是后退操作,且当前指针小于数组总长度,直接截取指针之前的部分储存下来
          // 此操作来避免当点击后退按钮之后,再进行正常跳转,指针会停留在原地,而数组添加新hash路由
          // 避免再次造成指针的不匹配,我们直接截取指针之前的数组
         // 此操作同时与浏览器自带后退功能的行为保持一致
          if (this.currentIndex < this.history.length - 1) {
             this.history = this.history.slice(0, this.currentIndex + 1)
             this.history.push(this.currentUrl)
             this.currentIndex++
           }
        }
       this.routes[this.currentUrl]()
       this.isBack = false
    }

}


Router.route('/home', () => {
    console.log('----home----')
})

Router.route('/about', () => {
    console.log('----about----')
})

2.History路由

 

 

class Routers {
   constructor() {
      this.routes = {}
      // 在初始化时监听popstate事件
      this._bindPopState()
    }
   // 初始化路由
    init(path) {
          history.replaceState({path: path}, null, path)
         this.routes[path] && this.routes[path]()
    }
  // 将路径和对应回调函数加入hashMap储存
  route(path, callback = () => {}) {
      this.routes[path] = callback
    }
  // 触发路由对应回调
  go(path) {
        history.pushState({path: path}, null, path)
       this.routes[path] && this.routes[path]()
    }
   // 监听popstate事件
   _bindPopState() {
      window.addEventListener('popstate', e => {
          const path = e.state && e.state.path
          this.routes[path] && this.routes[path]()
      })
   }
}

 

 

posted @ 2021-04-22 14:50  duqianqian  阅读(1279)  评论(0编辑  收藏  举报