超詳細!Vue-Router手把手教程

最近在重溫vue全家桶,再看一遍感覺記憶更深刻,所以專門記錄一下(本文vue-router版本為v3.x)。

1,router-view

<router-view>是一個功能性組件,用于渲染路徑匹配到的視圖組件。可以配合<transition><keep-alive>使用。如果兩個一起用,要確保在內層使用<keep-alive>。

<router-view></router-view>
<!--或-->
<router-view name="footer"></router-view>

如果<router-view>設置了名稱,則會渲染對應的路由配置中 components下的相應組件。

2,router-link

<router-link>標簽支持用戶在具有路由功能的應用中(點擊)導航。

屬性 類型 說明
to String/Object 目標路由/目標位置的對象
replace Boolean 不留下導航記錄
append Boolean 在當前路徑后加路徑 /a => /a/b
tag String 指定渲染成何種標簽
active-class String 激活時使用的Class
<router-link :to="{ path: '/login'}" replace tag="span"></router-link>

3,重定向redirect

根路由重定向到login

const router = new VueRouter({
  routes: [
    { path: '/', redirect: '/login' }
  ]
})

動態(tài)返回重定向目標

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: to => {
      // 方法接收 目標路由 作為參數
      // return 重定向的 字符串路徑/路徑對象
    }}
  ]
})

4,路由別名

路由訪問/b時,URL會保持為/b,但是路由匹配則為/a

const router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]
})

5,路由傳參props

使用props,避免和$route過度耦合,這樣就可以直接在組件中使用props接收參數

5.1,布爾模式

在路由后面寫上參數,并設置propstrue

{
    path: '/vuex/:id',
    name: 'Vuex',
    component: () => import('@/view/vuex'),
    props: true,
    mate: {
        title: 'vuex'
    }
}

設置跳轉需要傳遞的參數params

<router-link :to="{name:'Vuex', params: {id: '99999'}}" tag="h1">跳轉</router-link>
<!--或者-->
toNext() {
    this.$router.push({
        name: 'Vuex',
        params: {
            id: '99999'
        }
    })
}

在跳轉過去的頁面,通過props或者this.$params取參

props: {
    id: {
        type: String,
        default: ''
    }
}
<!--或者-->
this.$params.id

5.2,對象模式

在路由中設置props為對象,攜帶靜態(tài)數據

{
    path: '/vuex',
    name: 'Vuex',
    component: () => import('@/view/vuex'),
    props: {
        id: '99999'
    },
    mate: {
        title: 'vuex'
    }
}

跳轉

<router-link :to="{name:'Vuex'}" tag="h1">跳轉</router-link>
<!--或者-->
toNext() {
    this.$router.push({
        name: 'Vuex'
    })
}

在跳轉過去的頁面,通過props或者this.$params取參

props: {
    id: {
        type: String,
        default: ''
    }
}
<!--或者-->
this.$params.id

注意:只適用于靜態(tài)數據

5.3,函數模式

先在路由中設置propsFunction,return一個對象,不管是query傳參還是params傳參,都可以轉為props

{
    path: '/vuex',
    name: 'Vuex',
    component: () => import('@/view/vuex'),
    props: route => ({
        <!--query-->
        id: route.query.id,
        <!--params-->
        age: route.params.age
    }),
    mate: {
        title: 'vuex'
    }
}

跳轉

<router-link :to="{name:'Vuex',query: {id: '99999'}, params:{age:'20'}}" tag="h1">跳轉</router-link>
<!--或者-->
toNext() {
    this.$router.push({
        name: 'Vuex',
        query: {
            id: '999999'
        },
        params: {
            age: '20'
        }
    })
}

在跳轉過去的頁面,通過props或者this.$route.params / this.$route.query取參

props: {
    id: {
        type: String,
        default: ''
    },
    age: {
        type: String,
        default: ''
    }
}
<!--或者-->
this.$route.query
this.$route.params

6,路由守衛(wèi)

路由守衛(wèi)主要用來通過跳轉或取消的方式守衛(wèi)導航。

6.1,全局前置守衛(wèi)beforeEach

當一個導航觸發(fā)時,全局前置守衛(wèi)按照創(chuàng)建順序調用。守衛(wèi)是異步解析執(zhí)行,此時導航在所有守衛(wèi)解析完之前一直處于等待中。

參數 說明
to 即將要進入的目標路由對象
from 當前導航正要離開的路由
next 回調方法

next用法如下

語法 說明
next() 進行下一個鉤子
next(false) 中斷導航,URL如已改,則重置到from的地址
next('/') 中斷當前跳轉并到其他地址,可設置路由對象
next(error) 導航終止并傳遞錯誤給onError()
const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})

6.2,全局解析守衛(wèi)beforeResolve

2.5.0新增,和beforeEach類似,區(qū)別是在導航被確認之前,同時在所有組件內守衛(wèi)和異步路由組件被解析之后,解析守衛(wèi)就被調用。

router.eforeResolve((to, from, next) => {
  // ...
})

6.3,全局后置鉤子afterEach

后置守衛(wèi)不會接受next函數也不會改變導航本身

router.afterEach((to, from) => {
  // ...
})

6.4,路由獨享守衛(wèi)beforeEnter

可以在路由配置上直接定義專屬的beforeEnter守衛(wèi),與全局前置守衛(wèi)的方法參數是一樣的。

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

6.5,組件內的守衛(wèi)

  • beforeRouteEnter

該守衛(wèi)不能訪問this,因為守衛(wèi)在導航確認前被調用,因此即將登場的新組件還沒被創(chuàng)建??梢酝ㄟ^傳一個回調給next來訪問組件實例。在導航被確認的時候執(zhí)行回調,并且把組件實例作為回調方法的參數。

const Footer = {
  template: `...`,
  beforeRouteEnter(to, from, next) {
    next(vm => {
        // 通過 `vm` 訪問組件實例
    })
  }
}
  • beforeRouteUpdate (2.2 新增)

在當前路由改變,但是該組件被復用時調用,可以訪問組件實例this。

const Foo = {
  template: `...`,
  beforeRouteUpdate(to, from, next) {
    this.name = to.params.name
    next()
  }
}
  • beforeRouteLeave

導航離開該組件的對應路由時調用,通常用來禁止用戶在還未保存修改前突然離開。可以通過next(false)來取消。

const Foo = {
  template: `...`,
  beforeRouteLeave(to, from, next) {
    const answer = window.confirm('確認要離開嗎')
    if (answer) {
        next()
    } else {
        next(false)
    }
  }
}

6.6,完整的導航解析流程

  1. 導航被觸發(fā)。
  2. 在失活的組件里調用beforeRouteLeave守衛(wèi)。
  3. 調用全局的beforeEach守衛(wèi)。
  4. 在重用的組件里調用beforeRouteUpdate守衛(wèi) (2.2+)。
  5. 在路由配置里調用beforeEnter。
  6. 解析異步路由組件。
  7. 在被激活的組件里調用beforeRouteEnter
  8. 調用全局的beforeResolve守衛(wèi)(2.5+)。
  9. 導航被確認。
  10. 調用全局的afterEach鉤子。
  11. 觸發(fā)DOM更新。
  12. 調用beforeRouteEnter守衛(wèi)中傳給next的回調函數,創(chuàng)建好的組件實例會作為回調函數的參數傳入。

7,路由元信息

定義路由的時候可以配置meta對象字段,用來存儲每個路由對應的信息。通過this.$route.meta來訪問,或者在路由守衛(wèi)中通過to.metafrom.meta訪問。

const router = new VueRouter({
  routes: [
    {
        path: '/index',
        name: 'Index',
        component: () => import('@/view/index'),
        meta: {
            title: '首頁',
            rolu: ['admin', 'boss']
        }
    }
  ]
})

8,過渡動效

只需要使用transition標簽包裹住router-view標簽即可,動畫效果可以自己定義,參考transition組件的用法。也可以在父組件或者app.js中使用watch監(jiān)聽$route變化,根據不同路由替換transition組件的name屬性,實現不同的動畫效。

<transition :name="transitionName">
  <router-view></router-view>
</transition>

監(jiān)聽

watch: {
  '$route' (to, from) {
    const toD = to.path.split('/').length
    const fromD = from.path.split('/').length
    this.transitionName = toD < fromD ? 'slide-right' : 'slide-left'
  }
}

9,滾動行為

當創(chuàng)建Router實例時,可以提供一個scrollBehavior方法,并接收tofrom路由對象。第三個參數savedPosition只有通過瀏覽器的前進/后退按鈕觸發(fā)時才可用。

const router = new VueRouter({
    mode: 'hash',
    routes,
    scrollBehavior(to, from, savedPosition) {
        if (savedPosition) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(savedPosition)
                }, 1000)
            })
        } else {
            return { x: 0, y: 0 }
        }
    }
})

10,完整路由配置

首先導入Vuevue-router,然后使用router,定義路由信息集合,每個路由都是一個對象,對象擁有如下屬性

屬性 類型
path String 組件路徑信息
name String 組件命名
component Function 組件
mate Object 元信息
children Object 子路由
redirect String 重定向
props Boolean/Object/Function 參數傳遞

具體代碼如下:

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)

const routes = [
    {
        path: '/',
        redirect: '/index'
    },
    {
        path: '/index',
        name: 'Index',
        component: () => import(/* webpackChunkName: "index" */ '@/view/index'),
        mate: {
            title: '首頁',
            auth: false
        }
    },
    {
        path: '/login',
        name: 'Login',
        component: () => import(/* webpackChunkName: "login" */ '@/view/login'),
        meta: {
            title: '登錄',
            auth: false
        },
        children: [
            {
                path: 'children',
                name: 'Children',
                component: () => import(/* webpackChunkName: "children" */ '@/view/children'),
                mate: {
                    title: '嵌套的子路由',
                    auth: false
                }
            }
        ]
    }
]

const router = new VueRouter({
    mode: 'hash',
    routes
})

export default router

注意:嵌套子路由必須在被嵌套的頁面放置<router-view>標簽。


本次分享就到這兒啦,我是@鵬多多,如果您看了覺得有幫助,歡迎評論,關注,點贊,轉發(fā),我們下次見~

往期文章

個人主頁

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容