1.Vue-Router本质

根据"不同的hash值“或者”不同的路径地址", 将不同的内容渲染到router-view
所以实现VueRouter的核心关键点就在于如何监听’hash’或’路径’的变化, 再将不同的内容写到router-view中

hash

 <a href="#/home">首页</a><a href="#/about">关于</a><div id="html"></div>
 // hashchange监听hash的变化window.addEventListener('hashchange', ()=>{// console.log('当前的hash值发生了变化');let currentHash = location.hash.slice(1);console.log(location,currentHash);document.querySelector('#html').innerHTML = currentHash;})// 路径一开始就有hash,load 监听网络加载完成window.addEventListener('load', ()=>{let currentHash = location.hash.slice(1);document.querySelector('#html').innerHTML = currentHash;})

路径

 <a onclick="go('/home')">首页</a><a onclick="go('/about')">关于</a><div id="html"></div>
 function go(path) {console.log(path);history.pushState(null, null, path);document.querySelector('#html').innerHTML = path;}// popstate监听前进或者后退window.addEventListener('popstate', ()=>{console.log('点击了前进或者后退', location.pathname);document.querySelector('#html').innerHTML = location.pathname;})

history.pushState(参数1, 参数2,参数3)

参数1:对象
参数2:当前网络标题(会自动被所有浏览器忽略)
参数3:path(需要追加的路径)

手写vue-router

// 保存相关信息,方便后面注入(this.$router, this.$route)
class SueRouteInfo {constructor(){// 保存当前地址this.currentPath = null}
}
class SueRouter {constructor(options){this.mode = options.mode || 'hash' // 路由模式,未指定则默认为hashthis.routes = options.routes || []/*** 改造配置路由* 可以根据路由地址获取到对应的组件* key:路由地址* value:组件*/// 提取路由信息/*** {*  '/home': Home,*  '/about': About* }*/this.routesMap = this.createRoutesMap()console.log(this.routes,this.routesMap);this.routeInfo = new SueRouteInfo()// 初始化默认的路由信息this.initDefault()}initDefault(){if(this.mode === 'hash'){console.log('location.hash', location.hash);// 1.判断打开的界面有没有hash, 如果没有就跳转到#/if(!location.hash){location.hash = '/'}// 2.加载完成之后和hash发生变化之后都需要保存当前的地址window.addEventListener('load', ()=>{this.routeInfo.currentPath = location.hash.slice(1)})window.addEventListener('hashchange', ()=>{this.routeInfo.currentPath = location.hash.slice(1)})}else {console.log('location.pathname', location.pathname);// 判断打开的界面有没有路径, 如果没有就跳转到/if(!location.pathname){location.pathname = '/'}// 加载完成之后和history发生变化之后都需要保存当前的地址window.addEventListener('load', ()=>{this.routeInfo.currentPath = location.pathname})window.addEventListener('popstate', ()=>{this.routeInfo.currentPath = location.pathname})}}createRoutesMap(){return this.routes.reduce((map, route)=>{map[route.path] = route.componentreturn map},{})}
}
SueRouter.install = (Vue, options) => {Vue.mixin({beforeCreate(){console.log('this.$options', this.$options);/*** import router from './router'* this.$options.router * new Vue({router, render: h => h(App)}).$mount('#app')*/if(this.$options && this.$options.router){this.$router = this.$options.routerthis.$route = this.$router.routeInfoVue.util.defineReactive(this, 'xxx', this.$router);// 使用Vue.util.defineReactive的原因是 render在load之前执行// currentPath 双向绑定}else {this.$router = this.$parent.$routerthis.$route = this.$router.routeInfo}}})/*只要外界使用了Vue-Router, 那么我们就必须提供两个自定义的组件给外界使用只要外界通过Vue.use注册了Vue-Router, 就代表外界使用了Vue-Router只要接通通过Vue.use注册了Vue-Router, 就会调用插件的install方法所以我们只需要在install方法中注册两个全局组件(router-link router-view)给外界使用即可 // * */Vue.component('router-link',{props:{to: String},render(){/*** 注意点: render方法中的this并不是当前实例对象, 而是一个代理对象如果我们想拿到当前实例对象, 那么可以通过this._self获取*//*** this._self 才能拿到当前Vue实例*/// history / hash:this._self.$router.modelet path = this.to // this.to不能直接修改if(this._self.$router.mode === 'hash'){path = '#' + path}return <a href={path}>{this.$slots.default}</a> // 获取内容 this.$slots.default}})Vue.component('router-view', {render(h){let routesMap = this._self.$router.routesMap;let currentPath = this._self.$route.currentPath;let currentComponent = routesMap[currentPath]return h(currentComponent)}})
}
export default SueRouter;

学习记录❥(^_-)

手撕Vue-Router相关推荐

  1. Vue 源码之手写Vue Router

    Vue 源码之手写Vue Router 源码地址:https://github.com/CONOR007/Handwritten-routing 一.Vue Router的两种模式 hash模式实现原 ...

  2. Vue Router 原理分析与实现

    陈丹青:看过的东西走过的路,还有你所经历的一切,都会经历一个开眼界的过程. 但眼界开了并不是一件好事情,反而顿悟之后从此你就会知道,你在社会之中是完全没有位置可言的.我算个屁,什么事都有人做过,都有人 ...

  3. editor修改样式 vue_手摸手Electron + Vue实战教程(三)

    系列文章: 手摸手Electron + Vue实战教程(一) 手摸手Electron + Vue实战教程(二) ❝ 上一篇我们已经完成了左侧菜单栏的基本样式功能,这一篇我们就主要来开发右侧的Markd ...

  4. Vue Router 4.0 正式发布!焕然一新。

    关注若川视野,回复"pdf" 领取资料,回复"加群",可加群长期交流学习 12月8日,Vue Router 4 正式发布稳定版本. 在经历了 14 个 Alph ...

  5. Vue Router的详细教程

    Vue Router的详细教程 安装 #直接下载 / CDN https://unpkg.com/vue-router/dist/vue-router.js Unpkg.com 提供了基于 NPM 的 ...

  6. vue router children 路由变了 组件没变_Vue.js从零开始——路由(2)

    因为一些原因,我断更了几天时间,因为要准备面试 + 不在家,抱歉大家! 题图是一个大概的 Vue 模块化项目组成,当然因为我从网上找的,所以可以忽略当中的 Bulma,这其实是一个 CSS 框架,往简 ...

  7. 常见js手撕题及算法总结

    文章目录 实现一下观察者模式 实现一下工厂模式 实现一下单例模式 设计一个lazyMan,实现以下功能: 实现一个简单的EventEmitter 手撕实现原生js的一些方法(call.apply.bi ...

  8. 适合初学者练手的vue小项目(附github源码)

    vue慢慢的成为了前端最受欢迎的框架之一,在很多项目之中开发都能用得到,如今也已经发展到3.0了,可能是因为这个框架可以提高工作效率,因此受到大家的追捧,在之前的文章里面也说过,2019年,大前端学习 ...

  9. 手把手教你手撕SPF生成树(OSPF区域内防环)

    SPF生成树 一.基础知识 1.SPF的基本原理 2.LSA的类型 3.数据结构的一捏捏知识 二.准备工作 1.理论向实践转换 (1)节点和权重 (2)网段与节点之间的转换 2.实验环境搭建 三.实验 ...

最新文章

  1. WINCE6.0+S3C2443下ADC在电池驱动应用
  2. 完全虚拟化和半虚拟化区别
  3. 【iOS 开发】使用 iMazing 进行沙盒调试
  4. 集成测试变得简单的第1部分:存储库测试
  5. cocos2d-x3.6 连连看随机地图实现
  6. Unity ECS 初探
  7. 斗鱼php开发面经,斗鱼面经
  8. TCP/IP协议栈详解
  9. 金融计量模型(一):引言
  10. 如何用xilinx sdk输出hello world
  11. 2022年工作日节假日数据
  12. 导数乘法/除法法则的证明
  13. 【数据结构】AOE网——关键路径
  14. 编程c语言counter,c语言中计算平均分时,计数器(counter)的初始化
  15. html5 侧滑菜单,侧滑菜单
  16. 全网最详细的深度学习pytorch-gpu环境配置
  17. 1114:白细胞计数(C++)
  18. Python 远程(邮件)控制电脑升级版
  19. android sd卡名称,Android系统中SD卡各文件夹名称及功能详解
  20. Java多线程2.3.生产者与消费者之间的关系2

热门文章

  1. 绘制Python代码的UML图
  2. Qt网络编程——TCP
  3. 发布一个MsBuild任务组件-可用于同时发布多个网站
  4. Netty 源码深度解析(九) - 编码
  5. (一)linux下hadoop安装配置
  6. 「管理数学基础」1.1 矩阵理论:线性变换及其矩阵表示
  7. 打算_20160604
  8. PC-如何禁用 Cookie
  9. [转载]Jquery mobile 新手问题总汇
  10. OpenStack-Icehouse(nova-network)多节点基础环境部署