對於Vue內部來說,不管是根組件還是子組件,都存在this.$router和this.$route兩個屬性,它們的區別如下: $router 指向當前的VueRouter實例,也就是new Vue({router:router})這裡傳入的router實例對象,可以使用上一節里列出的VueRoute ...
對於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對象凍結並返回(即不允許新增屬性) }