vue-router原理
弄清vue-router大概原理可从以下3个问题出发
- 如何监听url变化
- vue插件使用,以及Vue.use(VueRouter)做了什么
- 如何渲染当前匹配组件
如何监听url变化
首先我们要知道前端路由,前端路由、后端路由都是一种相对概念,就是为了区分而起了个名字,就好比客户端渲染和服务端渲染,他们都是成对出现的,在没有客户端渲染的时候应该没人会把从服务器获取完整的html文档叫服务端渲染把,前端路由也是如此。
前端路由的特点就是,相对后端路由,改变url,页面无需刷新。
前端路由有两种实现方式,hash模式和h5 history模式
hash模式
通过改变url # 后面的内容来改变url,可用window.location.hash改变hash值,利用window.onhashchange来监听hash变化
history模式
相对hash更灵活,没有只能修改#后面的内容的限制,可利用pushState和replaceState来改变url,利用window.onpopstate来监听url变化
vue插件使用
知道了怎么跳转及监听url变化,现在需要利用插件和vue结合起来
why use Vue.use? 在模块化环境下,插件里是没有Vue的,所以得有一个机制把Vue作为参数传入,就是Vue.use。
为啥不在插件import Vue from 'vue'而是通过参数传入Vue呢,个人理解
- 写插件时,不应该和外部环境耦合,造成代码侵入
- 代码单元测试时不一定需要用到vue,如果没有安装vue,造成报错
- 如果每个插件都去安装一遍vue,太浪费了
- 实在不雅
通过Vue.use安装了插件,并调用install方法,这时做了什么?
既然use是为了拿到Vue,那么肯定就是要用它,且看看删减版源码
function install (Vue) {
// 1
Vue.mixin({
beforeCreate: function beforeCreate () {
if (isDef(this.$options.router)) { // 对new Vue({router:router})你应该有印象,这里说明有router就是根实例
this._routerRoot = this;
this._router = this.$options.router;
this._router.init(this); //调用init方法,主要是处理首次进入和设置url变化监听
Vue.util.defineReactive(this, '_route', this._router.history.current); // 把_route属性变为响应式的,后面只需要改变_route就会触发更新
} else { // 否则就从父组件的找
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
}
},
});
// 2
Object.defineProperty(Vue.prototype, '$router', { // 方便 this.$router使用
get: function get () { return this._routerRoot._router }
});
Object.defineProperty(Vue.prototype, '$route', {// 方便 this.$route使用
get: function get () { return this._routerRoot._route }
});
// 3
Vue.component('RouterView', View); // 注册router-view组件
Vue.component('RouterLink', Link); // 注册router-link
}
这里很重要的一点就是Vue.util.defineReactive(this, '_route', this._router.history.current),当监听到url变化,我们把url赋给_route,这样就触发了组件更新
history.listen(function (route) {
this$1.apps.forEach(function (app) {
app._route = route;
});
});
如何渲染当前匹配组件
首先是根据当前route去匹配对应的组件,然后就是router-view去渲染对应的组件
关于router-view,你可能会很好奇,它是怎么实现动态切换组件的,我一开始以为是v-if,v-else-if什么的,但是感觉太low了吧,所以这个组件用template显然不合理,那么就得用到 render函数 了, 实现灵活的动态渲染。
// 源码中router-view render函数并非这样,这里只做原理解释
function render(createElement){
return createElement(matchedCoponent)
}
不得不说,vue用起来简单,但想要用好,首先一定要多了解文档,然后就是看个人如何灵活运用了。看源码也挺重要,但是需要一定要带着问题看,非相关代码一律按纸老虎处理,否则会看的很迷
总结一下vue-router原理
- 前端路由实现页面不刷新,有hash和history模式,通过onhashchange或onpopstate来监听url变化
- Vue.use使用VueRouter,传入Vue,通过混入在beforeCreate做了一些route的定义和调用Vue.util.defineReactive使之变成响应式,使的url变化时可以触发组件更新
- 在Vue原型定义了$router和$route,注册了router-view和router-link组件
- router-view是通过编写render函数,而非template,来实现动态渲染的
本文地址:https://blog.csdn.net/illusion_melody/article/details/109368237