Vue路由 ---- vue-router

vue-router 中常用的 hash 和 history 路由模式实现原理吗?

Two Point!!!

  • spa页面不能刷新:
    // 1.hash
    // 2.history api

  • url变化显示对应内容:
    // 1.router-view:占位容器
    // 2.数据响应式,current路由 变化触发视图更新;
    响应式得两种实现方式?

    • 方式1:借鸡生蛋 - new Vue({data: {current: '/'}})
    • 方式2:Vue.util.defineReactive(obj, 'current', '/')

hash 模式的实现原理

早期的前端路由的实现就是基于 location.hash 来实现的。其实现原理很简单,location.hash 的值就是 URL 中 # 后面的内容。比如下面这个网站,它的 location.hash 的值为 '#search':

https://www.word.com#search

hash 路由模式的实现主要是基于下面几个特性:
  • URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;

  • hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换;

  • 可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用 JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值;

  • 我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。

依据配置的路由表进行路由匹配 ---- > routeMap获取需要更新的组件

history 模式的实现原理

HTML5 提供了 History API 来实现 URL 的变化。其中做最主要的 API 有以下两个:history.pushState() 和 history.repalceState()。这两个 API 可以在不进行刷新的情况下,操作浏览器的历史纪录。唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示:

window.history.pushState(null,null, path);
window.history.replaceState(null,null, path);

history 路由模式的实现主要基于存在下面几个特性:

  • pushState 和 repalceState 两个 API 来操作实现 URL 的变化 ;

  • 使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染);

  • history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)。

注意:
  • histroy模式需要后端配合配置;eg: nginx
  • 本地路由需要匹配404页面,路由配置在最后 *;

hash和histrory比较

hash 模式相比于 history 模式的优点:

  • 兼容性更好,可以兼容到IE8
  • 无需服务端配合处理非单页的url地址

hash 模式相比于 history 模式的缺点:

  • 路径多个#,比较丑
  • 导致锚点功能失效
  • 相同 hash 值不会触发动作将记录加入到历史栈中,而 pushState 则可以。

综上所述,当我们不需要兼容老版本IE浏览器,并且可以控制服务端覆盖所有情况的候选资源时,可以使用 history 模式了

手写实现简单vue-router

let Vue;

// 1.实现插件
class VueRouter {
  constructor(options) {
    this.options = options;

    // 数据响应式,current必须是响应式的,这样他变化,使用它的组件就会重新render
    Vue.util.defineReactive(
      this,
      "current",
      window.location.hash.slice(1) || "/"
    );

    // 监控url变化
    window.addEventListener("hashchange", () => {
      this.current = window.location.hash.slice(1);
    });
  }
}

// Vue插件要实现一个install方法
VueRouter.install = function(_Vue) {
  Vue = _Vue;

  // 注册router实例
  // 通过全局混入:Vue.mixin({beforeCreate})
  Vue.mixin({
    beforeCreate() {
      // 仅在根组件创建时执行一次,Vue实例则有该$router
      if (this.$options.router) {
        Vue.prototype.$router = this.$options.router;
      }
    },
  });

  // 注册router-view和router-link
  Vue.component("router-view", {
    render(h) {
      // url => component
      // url
      // window.location.hash
      // router: this.$router
      let component = null;
      const { current, options } = this.$router;
      // 简易的路由表匹配
      const route = options.routes.find((route) => route.path === current);
      if (route) {
        component = route.component;
      }
      console.log(current, options);
      return h(component);
    },
  });
  Vue.component("router-link", {
    props: {
      to: {
        type: String,
        required: true,
      },
    },
    render(h) {
      // <router-link to="/about">xxx</router-link>
      // <a href="#/about">xxx</a>
      // JSX写法:  return <a href={"#" + this.to}>{this.$slots.default}</a>;
      return h("a", { attrs: { href: "#" + this.to } }, this.$slots.default);
    },
  });
};

export default VueRouter;

STRONG

  • 查看vue-router源码,并自己尝试实现嵌套路由
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,135评论 6 514
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,317评论 3 397
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,596评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,481评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,492评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,153评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,737评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,657评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,193评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,276评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,420评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,093评论 5 349
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,783评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,262评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,390评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,787评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,427评论 2 359

推荐阅读更多精彩内容

  • 前言  在工作和面试中,Vue-router都是比较热的知识点,Vue中的路由解决方案是基于前端路由原理进行封装实...
    agamgn阅读 634评论 0 14
  • 一、vue-router实现原理 SPA(single page application):单一页面应用程序,只有...
    walycode阅读 1,052评论 1 3
  • 介绍 vue-router是一个vue插件。其实质是在location.hash、location.replace...
    AmazRan阅读 1,556评论 0 6
  • 时间总是不经意的从指间流逝,转眼便过去了这么久,2020已然过去了一半,时间匆匆,只有学习才能贯彻始终的陪伴着大家...
    WEB前端含光阅读 527评论 0 5
  • vue-router两种模式,hash,history 为了构建SPA(单页面应用),需要引入前端路由系统,这就是...
    丘可_2874阅读 4,715评论 1 1