1. Hash模式(基于锚点,以及onhashchange事件)

实现原理:

  • URL中 # 后面的内容作为路径地址
  • 监听hashchange事件
  • 根据当前路由地址找到对应的组建重新渲染

    2. History模式(基于HTML5中的History API)

    1. 说明

  • history.pushState(), IE10以后才支持

  • history.replaceState()```javascript // node.js服务器配置history模式 const path = require(“path”); const history = require(“connect-history-api-fallback”); const express = require(“express”); const app = express() // node.js中配置history模式 app.use(history()) app.use(express.static(path.join(__dirname, “../vue-router/dist”))) app.listen(9000, () => { console.log(“server is take on, port: 9000”) })

// nginx配置history模式 nginx.config文件中: location / { // 末尾添加 try_files $uri/ /index.html }

  1. <a name="4Xcnb"></a>
  2. ### 2. 实现原理
  3. - 通过history.pushState()方法改变地址栏
  4. - 监听popstate事件
  5. - 根据当前路由地址找到对应的组建重新渲染
  6. <a name="G44Ul"></a>
  7. ### 3. 实现
  8. <a name="OsQEj"></a>
  9. #### 实现视图
  10. 1. install静态方法, 用于对当前插件安装的处理
  11. 1. 三个实例属性
  12. - options, 保存routers配置
  13. - routeMap, 保存路由的键值对
  14. - data, 保存当前路由
  15. 3. createRouteMap实例方法, 遍历所有路由规则,以键值对的形式存储到routeMap中
  16. 3. initComponents实例方法, 定义router-link组件和router-view组件
  17. 3. initEvent实例方法, 用于监听popstate事件,当历史状态被激活的时候触发该事件,根据当前路由地址找到对应的组建重新渲染
  18. <a name="loqc4"></a>
  19. #### 实现代码
  20. ```javascript
  21. let _Vue = null
  22. export default class VueRouter {
  23. // 注册vue-router插件的时候调用:Vue.use(VueRouter)
  24. static install (Vue) {
  25. // 1 判断当前插件是否已经安装
  26. if (VueRouter.install.installed) {
  27. return
  28. }
  29. VueRouter.install.installed = true
  30. // 2 把Vue构造函数记录到全局变量
  31. _Vue = Vue
  32. // 3 把创建Vue实例时候传入的router对象注入到Vue实例上
  33. _Vue.mixin({
  34. beforeCreate () {
  35. // Vue实例
  36. if (this.$options.router) {
  37. _Vue.prototype.$router = this.$options.router
  38. this.$options.router.init()
  39. }
  40. }
  41. })
  42. }
  43. constructor (options) {
  44. this.options = options
  45. this.routeMap = {}
  46. this.data = _Vue.observable({
  47. current: '/'
  48. })
  49. }
  50. createRouteMap () {
  51. // 遍历所有路由规则,把路由规则解析成键值对形式存储到routeMap中
  52. this.options.routes.forEach(route => {
  53. this.routeMap[route.path] = route.component
  54. })
  55. }
  56. init () {
  57. this.createRouteMap()
  58. this.initComponents(_Vue)
  59. this.initEvent()
  60. }
  61. initComponents (Vue) {
  62. // router-link 组件
  63. Vue.component('router-link', {
  64. props: {
  65. to: String
  66. },
  67. // template: "<a :href='to'><slot></slot></a>"
  68. render (h) {
  69. return h(
  70. 'a',
  71. {
  72. attrs: {
  73. href: this.to
  74. },
  75. on: {
  76. click: this.clickHandler
  77. }
  78. },
  79. [this.$slots.default]
  80. )
  81. },
  82. methods: {
  83. clickHandler (e) {
  84. // 通过history.pushState()改变地址栏
  85. history.pushState({}, '', this.to)
  86. // 根据当前路由地址找到对应的组建重新渲染
  87. this.$router.data.current = this.to
  88. // hash模式:
  89. // window.location.hash = this.to
  90. // 阻止超链接对默认行为
  91. e.preventDefault()
  92. }
  93. }
  94. })
  95. const self = this
  96. // router-view 组件
  97. Vue.component('router-view', {
  98. render (h) {
  99. const component = self.routeMap[self.data.current]
  100. return h(component)
  101. }
  102. })
  103. }
  104. // 监听popstate事件
  105. initEvent () {
  106. window.addEventListener('popstate', () => {
  107. this.data.current = window.location.pathname
  108. })
  109. // hash模式
  110. // window.addEventListener('hashchange', (e) => {
  111. // this.data.current = e.newURL.split('#')[1]
  112. // })
  113. }
  114. };