vue路由实现

动态路由

路由规则填写props为true,在组件内部通过props获取对应路由参数,这里的路由参数理解为组件的属性
image.png

嵌套路由

将公共部分抽离需要渲染的部用router-view展示,Layout组件

编程式导航

$router.push('/') //不传参数
$router.push({name:'login',id:1}) //传参数
$router.replace() //不记录历史
$router.go(-1) //返回上一级
复制代码

hash模式和history模式区别

hash模式

  • url#后面内容作为路径地址
  • 监听hashchange事件
  • 根据当前路由地址找到对应法组件进行渲染

history模式

  • 通过history的pushState改变地址栏
  • 监听popstate事件
  • 根据当前路由地址找到对应的组件进行渲染

注意

  1. history模式下刷新浏览器会向服务端发送请求,在后端需要配置基于history模式支持
  2. nginx配置history

屏幕截图 2021-08-08 115242.png

vue-router模拟实现

类图

屏幕截图 2021-08-08 122333.png

分步拆解

  1. 创建install方法

router1.png

  1. 创建构造函数

router2.png

//创建响应式对象
Vue.observable({})
复制代码
  1. 创建routeMap

route3.png

  1. 创建router-link

image.png

  • 4.1 vue的构建版本

vue-build.png

  • 4.2 运行时版本Vue通过render函数渲染template

render.png

  • 4.3 阻止浏览器的默认行为,渲染对应组件

1.png

  1. 创建router-view

2.png

  1. initEvent函数,浏览器前进后退渲染对应视图

3.png

完整版vue-router

let _Vue = null
export class VueRouter {
  static install(Vue) {
    //1.判断当前插件是否已经被安装
    if (VueRouter.install.installed) {
      return
    }
    VueRouter.install.installed = true
    //2. 将Vue构构造函数记录到全局变量
    _Vue = Vue
    //3.将传入的router对象注入Vue实例
    _Vue.mixin({
      beforeCreate() {
        if (this.$options.router) {
          _Vue.prototype.$router = this.$options.router
          this._init()
        }
      }
    })
  }

  constructor(options) {
    this.options = options
    this.routeMap = {}
    this.data = _Vue.observable({
      current: '/'
    })
  }
  _init() {
    this.createRouteMap()
    this.initComponents()
    this.initEvent()
  }
  createRouteMap() {
    this.options.router.forEach(route => {
      this.routeMap[route.path] = route.component
    })
  }
  initComponents(Vue) {
    const that = this
    Vue.component('router-link', {
      props: {
        to: String
      },
      render(h) {
        return h(
          'a',
          {
            attrs: {
              href: this.to
            },
            on: {
              click: this.clickHandler
            }
          },
          [this.$slots.default]
        )
      },
      methods: {
        clickHandler(e) {
          history.pushState({}, '', this.to)
          this.$router.data.current = this.to
          e.preventDefault()
        }
      }
    })
    Vue.component('router-view', {
      render(h) {
        const component = that.routeMap[that.data.current]
        return h(component)
      }
    })
  }
  initEvent() {
    window.addEventListener('popstate', () => {
      this.data.current = window.location.pathname
    })
  }
}


复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享