🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[toc] 思路: vue-router的原理主要在于,它会监听路由的变化,然后根据路由对应的组件,在routeMap里去寻找需要渲染到页面上的组件,并通过h函数渲染到router-view上。 这里有两方面可以说的,一个是路由的两种模式,history和hash模式,另外一个就是new Router这个过程发生了是什么 vue router在创建后会被挂载到vue实例上,使得vue可以通过this.$router操作router vue-router存在两种模式,history模式和hash模式 ### 1.vue-router核心原理 监听页面路由的变化,在routeMap里找到对应路由需要渲染的组件,并通过render函数 渲染到router ### 2.new Router的时候以及挂载router对象的时候发生了什么 #### 1.new Router过程 1.首先new Router对象的时候,会把传入routes数组传入,并建立一套path和组件的routeMap映射关系 2.监听path变化的事件,比如load, hashchange(hash模式), popState(history模式),并且通过vue提供的defineReactive方法,将path变成响应式的,这样会触发router-view组件的render函数,根据path获取对应的component,通过h函数渲染出来 3.为什么defineReactive把path变成响应式了,就可以触发render的更新? 这里用了一个发布订阅的思想,在渲染router-view组件的时候,获取了path,这个时候添加了一个watcher,并且收集到dep中,当path改变的时候,就会通知dep上的notify()发布方法,通知watcher执行update,使得router-view重新渲染了 #### 2.挂载过程 1.构造函数提供一个install方法,接收传入的Vue构造函数 2.混入mixin 的beforeCreate生命周期,在这时挂载$router 3.在全局上创建两个组件,router-link和router-view,router-link控制路由的跳转,router-view或租routeMap中对应的组件,并通过render函数渲染出来 ```js Vue.mixin({ beforeCreate() { // 全局混入,将来在组件实例化的时候才执行 // 此时 router 实例已经存在 // this 代表组件实例 if (this.$options.router) { // 挂载 Vue.prototype.$router = this.$options.router } } }) ``` ### 2.history模式和hash模式 1.history和hash在显示上的区别在于url后缀里hash模式多了一个#号 2.hash模式修改的是锚点之后的url,并不会引起页面的刷新,监听的是window的load以及hashchange事件 ```js // 监听事件 window.addEventListener('hashchange', this.onHashChange.bind(this)) window.addEventListener('load', this.onHashChange.bind(this)) // 将 # 号后面的字符串截取 onHashChange() { this.current = window.location.hash.slice(1) } ``` 3.history模式没有#,修改路由会导致页面的刷新,这里跳转页面用的是h5提供的popstate以及replaceState方法,这两个方法改变url的path部分不会引起页面刷新 ```js history.pushState(null, '', el.getAttribute('href')) ``` 4.history模式下的vue项目,需要后端配置路由 ```js location / { try_files $uri $uri/ /index.html; } ```