Vue-Router 源码解析(四) $router和$route的区别
对于vue内部来说,不管是根组件还是子组件,都存在this.$router和this.$route两个属性,它们的区别如下:
$router 指向当前的vuerouter实例,也就是new vue({router:router})这里传入的router实例对象,可以使用上一节里列出的vuerouter实例的属性和方法
$route 指向当前跳转的路由对象,是一个包含当前的路由信息的对象,<router-view/>组件会通过这个属性来获取需要渲染的组件
对于$router来说,它包含了如下属性
- path ;当前路由的路劲,总是解析为绝对路劲 ;例如:/foo/bar
- params ;对象类型,包含了动态片段和全匹配片段,如果没有路由参数就是一个空对象
- query ;对象类型,表示url查询参数,对于/foo/user=1来说,$route.query.user等于1,如果没有查询参数,则是个空对象
- hash ;当前路由的hash值(带#),如果没有hash值,则为空字符串
- fullpath ;解析完成后的url,包含查询参数和hash的完整路劲
- matched ;一个数组,包含当前路由的所有嵌套路劲片段的路由记录,也就是所有父路由对象都在这个数组里面,<router-view/>组件会用到这个属性
- name ;当前路由的名称 ;和命名别名有关
- redirectedfrom ;重定向来源的路由的名字 ;和重定向及别名有关。
- meta ;meta值
name、meta这两个值就是创建vuerouter时,传入的router属性对应的每条路由记录的name和mata属性,其它的一般经过一些处理
writer by:大沙漠 qq:22969969
举个栗子:
<div id="app"> <router-link to="/login">登陆</router-link> <router-link to="/info/15">详情页</router-link> <hr/> <router-view></router-view> </div> <script> const login = { template:'<div>login page!</div>'} const info = { template:'<div>id:{{this.$route.params.id}}</div>'} const routes = [ {path:'/login',component:login,name:'login'}, {path:'/info/:id',component:info,name:'info'}, ] const app = new vue({ el:'#app', router:new vuerouter({routes}) }) </script>
渲染如下:
我们点击登陆路由到登陆页面,控制台输入app.$route,然后点击详情页,控制台再输入app.$route,打印分别如下:
login页面: info页面:
经常用到这个$route对象的地方就是在导航守卫里,参数2的to就是这个$route对象。
vuerouter安装的时候会执行它的install方法,该方法如下:
object.defineproperty(vue.prototype, '$router', { //vue实例的$router指向了this._routerroot._router get: function get () { return this._routerroot._router } }); object.defineproperty(vue.prototype, '$route', { //设置$route为this.$root._route get: function get () { return this._routerroot._route } });
通过执行object.defineproperty,我们在vue内部访问this.$router和this.$route都一直指向了this._routerroot._router和this._routeroot._route,而这两个属性是在vuerouter在安装的时候混入到vue的beforecreate生命周期函数内实现的,如下:
beforecreate: function beforecreate () { if (isdef(this.$options.router)) { //如果this.$options.router存在 ;就是在创建vue实例时传入的router对象 this._routerroot = this; //在vue实例上添加一个_routerroot指向自己,即vue实例 this._router = this.$options.router; //在vue实例上添加一个_router指向构造时的vue-router实例 this._router.init(this); //vue-router实例调用init()进行初始化,参数为vue实例 vue.util.definereactive(this, '_route', this._router.history.current); //通过vue的definereactive把_router变成响应式,等于this._router.history.current } else { this._routerroot = (this.$parent && this.$parent._routerroot) || this; } registerinstance(this, this); },
this._router.history.current等于vuerouter实例.history.current属性,在每次路由跳转后都会执行history原型上的updateroute方法,会在该方法内重置current属性,路由对象的创建如下:
function createroute(record, location, redirectedfrom, router) { //创建一个路由对象 record:路由记录信息 location:需要跳转的路由地址(包含path、query、hash和params的对象) redirectedform:未知 router:vue-router实例 var stringifyquery$$1 = router && router.options.stringifyquery; var query = location.query || {}; //重置query,如果未设置则重置为空对象 try { query = clone(query); } catch (e) {} var route = { //添加一个route对象 name: location.name || (record && record.name), //name信息 meta: (record && record.meta) || {}, //meta信息 path: location.path || '/', hash: location.hash || '', //路由的路劲 query: query, //路由的hash params: location.params || {}, //路由的params fullpath: getfullpath(location, stringifyquery$$1), //完整路劲 matched: record ? formatmatch(record) : [] //记录record 从当前到父节点一直到祖先节点的所有record }; if (redirectedfrom) { route.redirectedfrom = getfullpath(redirectedfrom, stringifyquery$$1); } return object.freeze(route) //最后将route对象冻结并返回(即不允许新增属性) }
推荐阅读
-
vue-router中的hash和history两种模式的区别
-
jQuery 源码解析(二十五) DOM操作模块 html和text方法的区别
-
Vue-Router 源码分析(三) VueRouter实例的属性和方法
-
vue中$route 和$router的区别
-
浅析vue-router中params和query的区别
-
Vue-router 中hash模式和history模式的区别
-
vue $router和$route的区别详解
-
Vue-Router 源码解析(五) router-link组件的用法及原理
-
Vue-Router 源码解析(四) $router和$route的区别
-
jQuery 源码解析(六) $.each和$.map的区别