一个vue路由工作流程1.前端路由和后端路由的区别后端路由输入url->向服务器发送请求->服务器解析请求的路径->fetch对应的页面->return出去到前端路由输入url->js解析地址->找到地址对应的页面->执行页面生成的js->看后端页面的路由时代,典型的mvc时代,前端路由是mvvm时代2,vue-router工作流程分析:当输入地址或url发生变化时,会触发windows下的监听事件。vue-router本身是一个对象,里面有一个current属性,current属性会发生变化,比如从首页route/到列表页route/listcurrent会变成/list,current是vue监控的,即vue将vue-router的current变量作为自己的数据进行监控。然后更新vue,获取新的组件,渲染组件问题:current是vue-router自身对象中的一个变量,怎么能被vue监控呢?如何定义一个对象属性来触发Vue的监控?通过vue.util方法的defineReactive进行监控。下面的例子会详细解释Hash和HistoryHash和History。使用Hash后,可以通过location.hash获取Hash的内容,通过onhashchangeHistoryHistory监听hash的变化,即正常路径可以通过location.pathname可以使用onpopstate监听历史变化。vue插件基础知识。vuex、vue-router、element-ui都是插件。Vue.use使用插件,会执行安装方法Vue.use(function(){console.log(1)})//会执行,输出1vara=function(){console.log(1)}a.install=function(){console.log('install')}Vue.use(a)//只会执行installVue.use()原理:如果你给它一个方法,它就会执行这个方法但是不管你给它什么,只要它上面有install属性,它就会执行installVue.mixin到vue全局Mix中的自定义操作vara=function(){console.log(1)}a.install=function(vue){vue.mixin({data(){return{c:123456//混入一个全局数据,可以直接在任何组件中使用}},methods:{//一些常用的方法可以混入vue的使用//比如弹窗消息弹出globalMethods:function(){console.log('我是全局的')}},//自定义生命周期,混合到所有vue实例中//所有组件在创建阶段执行我们mixin的这个操作created(){console.log('Iamcreated')console.log(this)//this指向当前组件}})}Vue.use(a)补充:Vue比较重要的api1,vue.utilvara=function(){console.log(1)}vartest={testa:1234}setTimeout(()=>{test.testa=4444},2000)//发现会变化,所以原来属于window的对象可以触发vue的监听,而从vuex派生出来的state不属于vue本身,但是可以触发View更新,原理是一样的a.install=function(vue){vue.util.defineReactive(test,'testa');vue.mixin({beforeCreate(){this.test=test;}})}Vue.use(a)2.vue.extend()一般用于单元测试constConstructor=Vue.extend(HelloWorldComponent)//创建这个组件的构造函数,即组件中的thisconstvm=newConstructor().$mount();3.vue.util.extend()其实就是一个对象的合并,所以可以用来复制。可以通过this.$options获取newVue的参数,实现一个简单的vue-routerclassHistory{constructor(){this.current=null;}}classvueRouter{constructor(options){this.mode=options.mode||'散列';this.routes=options.routes||[];this.routesMap=this.createMap(this.routes);this.history=newHistory();这个.init();}init(){if(this.mode=='hash'){//自动添加#location.hash?'':location.hash='/';window.addEventListener('load',()=>{this.history.current=location.hash.slice(1);})window.addEventListener('hashchange',()=>{this.history.current=location.hash.slice(1);})}}//目的是将routes数组变成键值对对象createMap(routes){returnroutes.reduce((memo,current)=>{memo[current.path]=current.component;returnmemo;},{})}}vueRouter.install=function(vue){//注意写法plugins判断插件是否注册if(vueRouter.install.installed)return;vueRouter.install.installed=true;vue.mixin({beforeCreate(){if(this.$options&&this.$options.router){this._root=this;this._router=this.$options.router;vue.util.defineReactive(this,'current',this._router.history);}else{this._root=this.$parent._root;}//为什么我们在访问router实例的时候使用this.$router//为什么要设置它像这样?目的是防止别人修改,只能读取,不能修改//this指向当前组件实例//在this下注册一个属性Object.defineProperty(this,'$router',{get(){返回这个._root._router;}})}})//router-view是vue自己注册的vue.component('router-view',{render(h){letcurrent=this._self._root._router.history.current;//对应每个组件的当前路径字符串
