后端路由: 输入url>请求发送到服务器>服务器解析请求的路径>拿取对应的页面>返回回去 前端路由: 输入url>js解析地址>找到对应的地址的页面>执行页面生成的js>看到页面
hash:
history:
如:vue-router、vuex、element-ui都是插件
插件基础点:
以下都是在main.js
执行
1、初始Vue.use()
Vue.use({ console.log('use') //会打印出use }) 复制代码
2、install属性
let a = function() { console.log(a) } //或 let a ={} a.install=function(){ console.log('install') } Vue.use(a) // 会打印install,而不会打印a。 // 如果你给他一个方法,他就执行这个方法, // 但是无论你给他的任何东西,只要给他一个install属性,他就会执行install。 复制代码
3、Vue.mixin()
let a = function() { console.log(a) } //或 let a ={} a.install=function(vue){ // Vue.mixin 全局混入自定义操作。上面的vue是作为参数传进来的,而不是import Vue from 'vue'中的Vue vue.mixin({ data () { return { c:123456 // 在其他页面this.c } }, methods:{ globalMethods(){ console.log('我是全局方法') // 在其它页面this.globalMethods() } }, created() { console.log(this) } }) } Vue.use(a) 复制代码
4、Vue工具类(Vue.util)
vue 工具类: defineReactive
、extend
、mergeOptions
、warn
let obj = { key:'KEY' } setTimeout(function () { obj.key='KEY2' // 3s改变{{this.obj1.key}} },3000) let a = function() { console.log(a) } //或 let a ={} a.install=function(vue){ console.log(vue.util) // vue 工具类: defineReactive、extend、mergeOptions、warn vue.util.defineReactive(obj,'key') // 监听。源码使用的是Object.defineProperty() vue.mixin({ beforeCreate(){ this.obj1=obj //在其他页面{{this.obj1.key}},值为KEY。 } }) } 复制代码
vue.extend() 与 vue.util.extend() 区别:
vue.extend() // 单元测试 const home = Vue.extend(home) // 新建这个组件的构造函数,也就是组件的this const vm = new home().$mount() vue.util.extend() // 浅拷贝对象 复制代码
准备完了前面几个知识点,我们下面来整代码,需要注意的是,下面只是个基础的vue-router,只可以页面切换。本篇只是为了熟悉源码,不为实际需要。
在src文件夹下新建一个文件夹myrouter,里面再新建一个index.js文件。
在原来的router文件夹里的index.js中把原来引入router的路径换为import VueRouter from '../myrouter'
编辑myrouter文件夹下的index.js
// 记录history对象 class HistoryRoute{ constructor(){ // 要监听的路径 this.current=null; } } // vuerouter本身 class vueRouter{ constructor(options){ this.mode=options.mode||'hash'; //配置模式 this.routes=options.routes||[]; // routes路由表 this.routesMap=this.createMap(this.routes); // 调用 createMap,参数是路由表routes this.history=new HistoryRoute;// 实例化history this.init(); // 初始化 } init(){ if(this.mode=='hash'){ // 判断是否是hash模式 location.hash?'':location.hash='/'; // 自动加#号。如果有hash返回空字符串。否则返回/ window.addEventListener('load',()=>{ // 监听页面加载完成 this.history.current=location.hash.slice(1); //拿到hash值,把#去掉。赋给实例化的history的current路径。 }) window.addEventListener('hashchange',()=>{ // 监听hash改变 this.history.current=location.hash.slice(1); }) } } // 路径对应组件。新组合一个对象。如:{'/':Home},也就是映射。 createMap(routes){ return routes.reduce((memo,current)=>{ // current 就是路由表routes memo[current.path]=current.component; return memo },{}) } } vueRouter.install=function(Vue){ // 写插件要注意判断插件是否注册 if(vueRouter.install.installed)return vueRouter.install.installed=true; // 向vue里面混入操作 Vue.mixin({ beforeCreate(){ if(this.$options&&this.$options.router){ // 在App.vue文件里如果有router选项的话 this._root=this; // 这里的this指向当前Vue实例,缓存下自身。 this._router=this.$options.router; // 挂载下选项里传进来的router. Vue.util.defineReactive(this,'current',this._router.history); //监听this.current,并且传入第三个参数。相当于children。 }else{ this._root=this.$parent._root; //如果没有就向上查找一级,直到查到App.vue里new Vue({router})为止。 } // 这个方法只是说明this.$router只读,私有变量思想 Object.defineProperty(this,"$router",{ //this指当前组件实例 get(){ return this._root._router; // 返回挂载后的router } }) } }) // 定义组件 Vue.component('router-view',{ render(h){ let current=this._self._root._router.history.current;// 拿到当前存进去的router实例里的current let routerMap=this._self._root._router.routesMap;//拿到当前存进去的router实例里的routesMap return h(routerMap[current]); // 拿到routerMap,调用h方法。渲染routerMap对应关系。放到router-view组件里面。 } }) } // 暴露vuerouter export default vueRouter; 复制代码
前端的路上我们一起前行。
你好,我是Vam的金豆之路,可以叫我豆哥。主要领域:前端开发。我的微信是 maomin9761,有什么疑问可以加我哦,自己创建了一个微信技术交流群,可以加我邀请你一起交流学习。最后自己也创建了一个微信公众号:前端历劫之路,欢迎关注。