Vue Router 核心原理及实现

前言

本文主要介绍 Vue Router 的核心原理以及如何实现一个简易版本的 Vue Router(history 和 hash 模式)关于VueRouter的使用,此处不再赘述。

一. 前置知识

hash 和 history 模式区别

  • 表现形式上:hash 模式 url https://localhost:8080?courseId=17#/detail?weekId=753&lessonId=3466, 带有 # 号。

  • 原理区别:hash 模式基于锚点,以及 onhashchange 事件。 history 模式是基于 HTML5 中的 history 模式。history.pushState、replaceState 在 IE10 以后才支持,存在兼容性问题。push 会向服务器发送请求,使用 pushState 不会发送请求,但是会在浏览器端产生历史记录,形成客户端路由。

  • history 模式使用

    1. 该模式需要服务器端的支持。
    2. 单页应用中,服务端不存在 www.testurl.com/login,地址会返回 404,提示找不到页面。
    3. history 模式下前后端工作过程:history 模式下,刷新页面会向服务器进行网络请求,后端处理
    4. history 模式,需要将默认的 html 文件返回给前端,前端获取到文件后再根据路由自行处理。

二. Vue Router实现

1.实现思路

  • 创建 VueRouter 插件,静态方法 install
    • 判断插件是否已经被加载
    • 当 Vue 加载的时候把传入的 router 对象挂载到 Vue 实例上(注意:只执行一次)
  • 创建 VueRouter 类
    • 初始化,options、routeMap、app(简化操作,创建 Vue 实例作为响应式数据记录当前路
      径)
    • initRouteMap() 遍历所有路由信息,把组件和路由的映射记录到 routeMap 对象中
    • 注册 popstate 事件,当路由地址发生变化,重新记录当前的路径
    • 创建 router-link 和 router-view 组件
    • 当路径改变的时候通过当前路径在 routerMap 对象中找到对应的组件,渲染 router-view

3.JavsScript版 类图

2.代码实现

let _Vue = null;
class VueRouter {
  static install(Vue) {
    //1 判断当前插件是否被安装
    if (VueRouter.install.installed) {
      return;
    }
    VueRouter.install.installed = true;
    //2 把Vue的构造函数记录在全局
    _Vue = Vue;
    //3 把创建Vue的实例传入的router对象注入到Vue实例
    // _Vue.prototype.$router = this.$options.router
    _Vue.mixin({
      beforeCreate() {
        if (this.$options.router) {
          _Vue.prototype.$router = this.$options.router;
        }
      },
    });
  }
  constructor(options) {
    this.options = options;
    this.routeMap = {};
    // observable
    this.data = _Vue.observable({
      current: "/",
    });
    this.init();
  }
  init() {
    this.createRouteMap();
    this.initComponent(_Vue);
    this.initEvent();
  }
  createRouteMap() {
    //遍历所有的路由规则 吧路由规则解析成键值对的形式存储到routeMap中
    this.options.routes.forEach((route) => {
      this.routeMap[route.path] = route.component;
    });
  }
  initComponent(Vue) {
    Vue.component("router-link", {
      props: {
        to: String,
      },
      render(h) {
        return h(
          "a",
          {
            attrs: {
              href: this.to,
            },
            on: {
              click: this.clickhander,
            },
          },
          [this.$slots.default]
        );
      },
      methods: {
        clickhander(e) {
          history.pushState({}, "", this.to);
          this.$router.data.current = this.to;
          e.preventDefault();
        },
      },
      // template:"<a :href='to'><slot></slot><>"
    });
    const self = this;
    Vue.component("router-view", {
      render(h) {
        // self.data.current
        const cm = self.routeMap[self.data.current];
        return h(cm);
      },
    });
  }
  initEvent() {
    //
    window.addEventListener("popstate", () => {
      this.data.current = window.location.pathname;
    });
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值