Vue路由原理

路由实现原理:

  • 控制地址栏的改变
  • 根据地址栏的改变来控制组件的切换

模式:

  • hash路由(hashchange)

hash路由的关键在于:在router-link中,调用window.location.hash改变页面的hash值,然后在router-view中在window对象上监听hashchange事件。

router-link:

<template>
  <div>
    <span @click="jump">
      <!-- 插槽显示组件调用时内部的内容 -->
      <slot></slot>
    </span>
  </div>
</template>

<script>
export default {
  // 通过prop属性to,接受外面传进来的参数
  props: ['to'],
  methods: {
    jump() {
      // 控制地址栏的改变
      window.location.hash = this.to
    }
  }
}
</script>
View Code

router-view:

<template>
  <div>
    <!-- 动态组件 -->
    <component :is='componentId'></component>
  </div>
</template>

<script>
import Recommend from '../components/Recommend'
import Singer from '../components/Singer'
import Rank from '../components/Rank'
export default {
  data: () => ({
    componentId: 'Recommend'
  }),
  components: {
    Recommend,
    Singer,
    Rank
  },
  created () {
    // 模拟路由表
    let routers = [
      {
        path: '/recommend',
        component: 'Recommend'
      },
      {
        path: '/singer',
        component: 'Singer'
      },
      {
        path: '/rank',
        component: 'Rank'
      }
    ]
    window.addEventListener('hashchange', () => {
      // 监听hash值的改变并截取hash值
      let hash = window.location.hash.split('#')[1]
      // 进行匹配
      routers.map((item) => {
        if(item.path === hash){
          this.componentId = item.component
        }
      })
    })
  }
}
</script>
View Code
  • history路由(popState)

history路由的关键在于:H5 history新增了两个API: history.pushState和history.replaceState

两个api都接受3个参数

  • 状态对象(state object):一个JavaScript对象,与用pushState()方法创建的新历史记录条目关联。无论何时用户导航到新创建的状态,popstate事件都会被触发,并且事件对象的state属性都包含历史记录条目的状态对象的拷贝。

  • 标题(title):FireFox浏览器目前会忽略该参数,虽然以后可能会用上。考虑到未来可能会对该方法进行修改,传一个空字符串会比较安全。或者,你也可以传入一个简短的标题,标明将要进入的状态。

  • 地址(URL): 新的历史记录条目的地址。浏览器不会在调用pushState()方法后加载该地址,但之后,可能会试图加载,例如用户重启浏览器。新的URL不一定是绝对路径;如果是相对路径,它将以当前URL为基准;传入的URL与当前URL应该是同源的,否则,pushState()会抛出异常。该参数是可选的;不指定的话则为文档当前URL。

以及在router-view中监听popstate事件

当活动历史记录条目更改时,将触发popstate事件。

需要注意的是调用history.pushState()或history.replaceState()不会触发popstate事件,只有在做出浏览器动作时,才会触发该事件,如用户点击浏览器的回退按钮。

router-link关键代码:

jump() {
  // 控制地址栏的改变
  // window.location.hash = this.to
  window.history.pushState(null,null, this.to)
  // 需要注意的是调用history.pushState()或history.replaceState()不会触发popstate事件。只有在做出浏览器动作时,才会触发该事件,如用户点击浏览器的回退按钮(或者在Javascript代码中调用history.back())
}
View Code

router-view关键代码:

window.addEventListener('popstate', () => {
  // 监听hash值的改变并截取hash值
  // console.log(window.history, window.location)
  let history = window.location.pathname
  console.log(history)
  // 进行匹配
  routers.map((item) => {
    if(item.path === history){
      this.componentId = item.component
    }
  })
})
View Code

其余代码与hash路由示例一样

当然这里只是简单的摊诉了路由的实现原理,如果要深入了解Vue的路由实现机制的可以查看vue的源码。

参考:https://juejin.im/post/5b40c1ede51d4518f140f84b

原文地址:https://www.cnblogs.com/jett-woo/p/12513112.html