vue-Router

198 阅读1分钟

Hash 模式

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

History 模式

  • 通过 history.pushState()方法改变地址栏
  • 监听 popstate 事件
  • 根据当前路由地址找到对应组件重新渲染
// router/index.js
import Router from 'vue-router'

//注册插件
Vue.use(VueRouter);
//创建路由对象
const router = new VueRouter({
  routes: [{ name: "home", path: "/"component:homeComponent }],
});

// main.js
// 创建Vue实例,注册 router对象
import router from './router'

new Vue({
  router,
  render:h=>h(App)
}).$mount('#app')

VueRouter(类图)

  • +options
  • +data
  • +routeMap

  • +constructor(Options):VueRouter
  • —install(vue):void
  • +init():void
  • +initEvent():void
  • +createRouteMap():void
  • initComponents(Vue):viod

install

let _Vue = null;
export default class VueRouter {
  static install(Vue) {
    // 1. 判断挡圈 插件是否已经安装
    if (VueRouter.install.installed) {
      return;
    }
    VueRouter.install.intalled = true;
    // 2. 把Vue构造函数记录到全局变量
    _Vue = Vue;
    // 3,把创建Vue实例时候传入router对象注入Vue实例上

    // 混入
    _Vue.mixin({
      beforeCreate() {
        if (this.$options.router) {
          _Vue.prototype.$router = this.$options.router;
          this.$options.router.init();
        }
      },
    });
  }
  constructor(options) {
    this.options = options;
    this.routeMap = {};
    this.data = _Vue.observable({
      current: "/",
    });
  }
  init() {
    this.createRouteMap();
    this.initeCompents(_Vue);
    this.initEvent()
  }
  createRouteMap() {
    //遍历所有的路由规则,把路由规则解析成键值对的形式 储存到routemap中
    this.options.routes.forEach((route) => {
      this.routeMap[route.path] = route.component;
    });
  }
  initComponents(Vue) {
    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();
        },
      },
      // template: '<a :href="to"><slot></slot></a>',
    });
    const self = this;
    Vue.component("router-view", {
      render(h) {
        const component = self.routeMap[self.data.current];
        return h(component);
      },
    });
  }
  initEvent(){
    window.addEventListener('popstate',()=>{
      this.data.current = window.location.pathname
    })
  }
}

Vue 的构建版本

  • 运行时版本:不支持 template 模板,需要打包的时候提前编译
  • 完整时版本:包含运行时和编译器,体积比运行时版本大 10k 左右,程序运行的时候把模板转换成 render 函数

    方法一

    //vue.config.js
    module.exports = {
      runtimeCompiler: true,
    };