摘要:而组件在创建时,又怎么会去调用呢这是由于将自身作为一个插件安装到了,通过注册了一个钩子函数,从而在之后所有的组件创建时都会调用该钩子函数,给了检查是否有参数,从而进行初始化的机会。
vue-router 是 Vue.js 官方的路由库,本着学习的目的,我对 vue-router 的源码进行了阅读和分析,分享出来给其他感兴趣的同学做个参考吧。
参考源码:vuejs/vue-router v2.2.1 - github
文档:vue-router 官方中文教程
初步我们分别从不同的视角来看 vue-router。
从开发者角度来看,是这样的:
var router = new VueRouter({ routes: [ {path: "/foo", component: {template: "FOO"}}, {path: "/bar", component: {template: "BAR"}} ] }) var vm = new Vue({ el: "#app", router: router })
我们创建一个 router,传入的 routes 中的每一项即为一条路由(route)配置,表示在匹配给定的地址时,应该使用什么组件渲染视图。
将 router 传入 new Vue() 用于创建根组件,这样根组件中对应的视图区域,可以基于 router 中的配置,根据页面地址显示不同的内容。当然,这还需要在组件模板中使用
从视图角度来看,是这样的:
......
页面地址变更后,
从数据角度来看,是这样的:
vm + _router | $router - history - matcher + _route | $route - matched
vm.$router 引用当前组件对应的 router 对象,该对象在初始化时(在 vm 创建过程中执行初始化),会启动对页面地址变更的监听,从而在变更时更新 vm 的数据($route),进而触发视图的更新。
深入如何实现对地址变更的监听?
对于缺省的 HashHistory 模式(也就是基于页面地址的 hash 部分来实现路由功能,如 http://example.com/path#/foo、http://example.com/path#/bar),是通过监听 hashChange 事件来实现:
window.addEventListener("hashchange", () => { // this.transitionTo(...) })
源码
这个动作是什么时候执行的呢?
是在 router.init()(源码)中调用的,而 router.init() 则是在根组件创建时(源码)调用的。
而 Vue 组件在创建时,又怎么会去调用 router.init() 呢?
这是由于 vue-router 将自身作为一个插件安装到了 Vue,通过 Vue.mixin() 注册了一个 beforeCreate() 钩子函数,从而在之后所有的 Vue 组件创建时都会调用该钩子函数,给了检查是否有 router 参数,从而进行初始化的机会。进而通过层层调用执行了监听 hashchange 事件的动作。
整理一下:
new Vue()
执行 vue-router 注入的 beforeCreate 钩子函数
执行 router.init(vm)
执行 history.setupListeners(),注册事件监听
地址变更如何通知到 vm?
这个过程比较简单,hashchange 时,执行 history.transitionTo(...),在这个过程中,会进行地址匹配,得到一个对应当前地址的 route,然后将其设置到对应的 vm._route 上。
只是进行了赋值,为什么 vm 就可以感知到路由的改变了呢?
答案在 vue-router 注入 Vue 的 beforeCreate 钩子函数中(源码):
Vue.util.defineReactive(this, "_route", this._router.history.current)
采用与 Vue 本身数据相同的“数据劫持”方式,这样对 vm._route 的赋值会被 Vue 拦截到,并且触发 Vue 组件的更新渲染流程。
地址变更如果同步视图更新?
接上一步,vm._route 已经接收到路由的变更,从而触发视图更新。而当视图更新进一步调用到
这里的主要处理逻辑是从根组件中取出当前的路由对象(parent.$route),然后取得该路由下对应的组件,然后交由该组件进行渲染:
return h(component, data, children)
这其中还涉及
其实 vue-router 从
vue-router 以插件方式“侵入”Vue,从而支持一个额外的 router 属性,以提供监听并改变组件路由数据的能力。这样每次路由发生改变后,可以同步到数据,进而“响应式”地触发组件的更新。
路由变更到视图变更的过程整理为:
hashchange --> match route --> set vm._route -->render() --> render matched component
实现过程中的技术点包括:
Vue 插件机制
响应式数据机制
Vue 渲染机制
地址变更监听
最后我写了一个应用 Vue.js、vue-router 以及其他 Vue 相关工具(Vuex、vue-loader)的示例,感兴趣可以看下:luobotang/vue-demo - github。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/88202.html
摘要:本文假设读者手里有关于和的文档,并且对和有一定的了解。没有文档也没关系我这里有关于文档以及介绍,可以配合本文进行学习。关键就是在中部导航栏热门,新上榜那块,棕色框内的内容会根据中部导航栏选中不同内容进行改变。 在这个教程里面,我会通过一系列的代码和图片来学习怎么使用vue-router,以及vuex。本文假设读者手里有关于vue-router和Vuex的文档,并且对Vue-router...
摘要:本文假设读者手里有关于和的文档,并且对和有一定的了解。没有文档也没关系我这里有关于文档以及介绍,可以配合本文进行学习。关键就是在中部导航栏热门,新上榜那块,棕色框内的内容会根据中部导航栏选中不同内容进行改变。 在这个教程里面,我会通过一系列的代码和图片来学习怎么使用vue-router,以及vuex。本文假设读者手里有关于vue-router和Vuex的文档,并且对Vue-router...
摘要:使用值来作路由。原生应用本身就是多页的场景,页面间状态的隔离比共享更重要一些。使用开发的是原生应用,页面栈的管理使用的也是原生的特性,没有但是有模块可以实现页面的前进和后退等操作。 系列文章的目录在 ? 这里 (由于 我比较懒 最近一段时间在忙其他事,系列文章拖了好久终于又更新了。。。) 什么是 vue-router ? vue-router 官方文档 vue-router 是针对 V...
阅读 1186·2021-11-24 09:38
阅读 2594·2021-09-27 14:00
阅读 1149·2019-08-30 15:55
阅读 1327·2019-08-30 14:16
阅读 1480·2019-08-30 10:54
阅读 2855·2019-08-28 17:58
阅读 748·2019-08-26 13:22
阅读 1220·2019-08-26 12:01