vue-router 的基本使用和路由守衛

路由中有三個基本的概念 route, routes, router

1, route,它是一條路由,由這個英文單詞也可以看出來,它是單數, Home按鈕 => home內容, 這是一條route, about按鈕 => about 內容, 這是另一條路由。

2, routes 是一組路由,把上面的每一條路由組合起來,形成一個數組。[{home 按鈕 =>home內容 }, { about按鈕 => about 內容}]

3, router 是一個機制,相當于一個管理者,它來管理路由。因為routes 只是定義了一組路由,它放在哪里是靜止的,當真正來了請求,怎么辦? 就是當用戶點擊home 按鈕的時候,怎么辦?這時router 就起作用了,它到routes 中去查找,去找到對應的 home 內容,所以頁面中就顯示了 home 內容。

4,客戶端中的路由,實際上就是dom 元素的顯示和隱藏。當頁面中顯示home 內容的時候,about 中的內容全部隱藏,反之也是一樣??蛻舳寺酚捎袃煞N實現方式:基于hash 和基于html5 history api.

vue-router中的路由也是基于上面的內容來實現的

在vue中實現路由還是相對簡單的。因為我們頁面中所有內容都是組件化的,我們只要把路徑和組件對應起來就可以了,然后在頁面中把組件渲染出來。

1, 頁面實現(html模版中)

在vue-router中, 我們看到它定義了兩個標簽<router-link> 和<router-view>來對應點擊和顯示部分。<router-link>就是定義頁面中點擊的部分,<router-view>定義顯示部分,就是點擊后,區配的內容顯示在什么地方。所以 <router-link>還有一個非常重要的屬性to,定義點擊之后,要到哪里去, 如:<router-link to="/home">Home</router-link>

2, js 中配置路由

首先要定義route, 一條路由的實現。它是一個對象,由兩個部分組成: pathcomponent。 path 指路徑,component 指的是組件。如:{path:’/home’, component: home}

我們這里有兩條路由,組成一個routes:

const routes = [
  { path: '/home', component: Home },
  { path: '/about', component: About }
]

最后創建router實例 對路由進行管理,它是由構造函數 new vueRouter()創建,接受routes 參數

const router = new VueRouter({
      routes // routes: routes 的簡寫
})

配置完成后,把router實例注入到 vue 根實例中,就可以使用路由了

const app = new Vue({
  router
}).$mount('#app')

執行過程:當用戶點擊router-link標簽時,會去尋找它的 to 屬性, 它的 to 屬性和 js 中配置的路徑{ path: '/home', component: Home} path 一一對應,從而找到了匹配的組件, 最后把組件渲染到 <router-view> 標簽所在的地方。所有的這些實現才是基于hash 實現的。

動態路由

上面我們定義的路由,都是嚴格匹配的,只有router-link 中的to屬性和 js 中一條路由route中 path 一模一樣,才能顯示相應的組件component. 但有時現實卻不是這樣的,當我們去訪問網站并登錄成功后,它會顯示 歡迎你,+ 你的名字。不同的用戶登錄, 只是顯示“你的名字” 部分不同,其它部分是一樣的。

這就表示,它是一個組件,假設是user組件。不同的用戶(就是用戶的id不同),它都會導航到同一個user 組件中。這樣我們在配置路由的時候,就不能寫死, 就是路由中的path屬性,不能寫死,那要怎么設置? 導航到 user 組件,路徑中肯定有user, id 不同,那就給路徑一個動態部分來匹配不同的id.

vue-router中,動態部分 以 : 開頭,那么路徑就變成了/user/:id, 這條路由就可以這么寫:{ path:"/user/:id", component: user }.

我們定義一個user組件(自己隨便寫一個就好了),頁面中再添加兩個router-link 用于導航, 最后router.js中添加路由配置,來體驗一下

app.vue 中添加兩個router-link:

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <header>
      <router-link to="/home">Home</router-link>
      <router-link to="/about">About</router-link>
     <!--  增加兩個到user組件的導航,可以看到這里使用了不同的to屬性 -->
      <router-link to="/user/123">User123</router-link>
      <router-link to="/user/456">User456</router-link>
    </header>
    <router-view></router-view>   
  </div>
</template>

index.js 配置user動態路由:

const routes = [
    {
        path:"/home",
        component: home
    },
    {
        path: "/about",
        component: about
    },
    /*新增user路徑,配置了動態的id*/
    {
        path: "/user/:id",
        component: user
    },
    {
        path: '/', 
        redirect: '/home' 
    }
]

user組件

<template>
    <div>
        <h1>User</h1>
        <div>我是user組件</div>
    </div>
</template>
<script>
    export default {

    }
</script>

這時在頁面中點擊user123 和user456, 可以看到它們都導航到user組件,配置正確。

在動態路由中,怎么獲取到動態部分? 因為在組件中是可以顯示不同部分的,就是上面提到的“你的名字”。其實,當整個vue-router 注入到根實例后,在組件的內部,可以通過this.$route來獲取到 router 實例。

//動態路由匹配
path:'/user/:id'
this.$route.params.id

它有一個params屬性,就是來獲得這個動態部分的。它是一個對象,屬性名,就是路徑中定義的動態部分 id, 屬性值就是router-link中to 屬性中的動態部分,如123。使用vuex時,組件中想要獲取到state 中的狀態,是用computed 屬性,在這里也是一樣,在組件中,定義一個computed 屬性**dynamicSegment**, user 組件修改如下:

<template>
    <div>
        <h1>User</h1>
        <div>我是user組件, 動態部分是{{dynamicSegment}}</div>
    </div>
</template>
<script>
    export default {
        computed: {
            dynamicSegment () {
                return this.$route.params.id
            }
        }
    }
</script>

這里還有最后一個問題,就是動態路由在來回切換時,由于它們都是指向同一組件,vue不會銷毀再創建這個組件,而是復用這個組件,就是當第一次點擊(如:user123)的時候,vue 把對應的組件渲染出來,但在user123, user456點擊來回切換的時候,這個組件就不會發生變化了,組件的生命周期不管用了。
這時如果想要在組件來回切換的時候做點事情,那么只能在組件內部(user.vue中)利用watch來監聽$route 的變化。把上面的代碼用監聽$route 實現

<script>
    export default {
        data () {
            return {
                dynamicSegment: ''
            }
        },
        watch: {
            $route (to,from){
                // to表示的是你要去的那個組件,from 表示的是你從哪個組件過來的,它們是兩個對象,你可以把它打印出來,它們也有一個param 屬性
                console.log(to);
                console.log(from);
                this.dynamicSegment = to.params.id
            }
        }
    }
</script>
tips:

this.$routethis.$router區別
this.$router是指整個大的路由實例對象
this.$route是當前路由相關的參數信息(想打印地址欄相關信息)

嵌套路由

嵌套路由,主要是由我們的頁面結構所決定的。當我們進入到home頁面的時候,它下面還有分類,如手機系列,平板系列,電腦系列。當我們點擊各個分類的時候,它還是需要路由到各個部分,如點擊手機,它肯定到對應到手機的部分。

在路由的設計上,首先進入到 home ,然后才能進入到phone, tablet, computer. Phone, tablet, compute 就相當于進入到了home的子元素。所以vue 提供了childrens 屬性,它也是一組路由,相當于我們所寫的routes。

首先,在home頁面上定義三個router-link 標簽用于導航,然后再定義一個router-view標簽,用于渲染對應的組件。router-link 和router-view標簽要一一對應。home.vue 組件修改如下:

<template>
    <div>
        <h1>home</h1>
<!-- router-link 的to屬性要注意,路由是先進入到home,然后才進入相應的子路由如 phone,所以書寫時要把 home 帶上 -->
        <p>
            <router-link to="/home/phone">手機</router-link>
            <router-link to="/home/tablet">平板</router-link>
            <router-link to="/home/computer">電腦</router-link>
        </p>
        <router-view></router-view>
    </div>
</template>

index.js 配置路由,修改如下:

const routes = [
    {
        path:"/home",
     // 下面這個屬性也不少,因為,我們是先進入home頁面,才能進入子路由
        component: home,
     // 子路由
        children: [
            {
                path: "phone",
                component: phone
            },
            {
                path: "tablet",
                component: tablet
            },
            {
                path: "computer",
                component: computer
            }
        ]
    },
    {
        path: "/about",
        component: about
    },
    {
        path: "/user/:id",
        component: user
    },
    {
        path: '/', 
        redirect: '/home' 
    }
]

這時當我們點擊home 時,它下面出現手機等字樣,但沒有任何對應的組件進行顯示,這通常不是我們想要的。要想點擊home時,要想渲染相對應的子組件,那還需要配置一條路由。當進入到home 時,它在children中對應的路由path 是空 ‘’,完整的childrens 如下:

children: [
    {
        path: "phone",
        component: phone
    },
    {
        path: "tablet",
        component: tablet
    },
    {
        path: "computer",
        component: computer
    },
    // 當進入到home時,下面的組件顯示
    {
        path: "",
        component: phone
    }
]

命名路由

命名路由,很簡單,因為根據名字就可以知道,這個路由有一個名字,那就直接給這個路由加一個name 屬性,就可以了。 給user 路由加一個name 屬性:

{
        path: "/user/:id",
        name: "user",
        component: user
}

命名路由的使用, 在router-link 中to屬性就可以使用對象了

//和下面等價
<router-link to="/user/123">User123</router-link> 
// 當使用對象作為路由的時候,to前面要加一個冒號,表示綁定
 <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>   

編程式導航:這主要應用到按鈕點擊上。當點擊按鈕的時候,跳轉另一個組件, 這只能用代碼,調用rourter.push()方法。 當們把router 注入到根實例中后,組件中通過this.$router可以獲取到router, 所以在組件中使用

this.$router.push("home")    //就可以跳轉到home界面

路由鉤子(路由守衛)

在某些情況下,當路由跳轉前或跳轉后、進入、離開某一個路由前、后,需要做某些操作,就可以使用路由鉤子來監聽路由的變化

vue路由鉤子大致可以分為三類:
1、全局鉤子
2、單個路由的鉤子
3、組件內鉤子

第一種 全局鉤子函數

主要包括beforeEach和aftrEach
beforeEach函數有三個參數:
to:router即將進入的路由對象
from:當前導航即將離開的路由
next:Function,進行管道中的一個鉤子,如果執行完了,則導航的狀態就是 confirmed (確認的);否則為false,終止導航。
afterEach函數不用傳next()函數
這類鉤子主要作用于全局,一般用來判斷權限,以及以及頁面丟失時候需要執行的操作
使用 router.beforeEach 注冊一個全局的 before 鉤子

    var routes = [{
      path:'/route1',
      name:'route1',
      component:() = > import('./index.vue')  //調用的時候再開始加載
    }]
     const router = new VueRouter({ 
        routes;
      })
     //開始注冊
  router.beforeEach((to, from, next) => {
    console.log('beforeEach')
    //next() //如果要跳轉的話,一定要寫上next()
    //next(false) //取消了導航
    next() //正常跳轉,不寫的話,不會跳轉
  })
  router.afterEach((to, from) => { // 舉例: 通過跳轉后改變document.title
    if( to.meta.title ){
      window.document.title = to.meta.title //每個路由下title
    }else{
      window.document.title = '默認的title'
    }
  })
第二種 針對單個路有鉤子函數

主要用于寫某個指定路由跳轉時需要執行的邏輯,只有beforeEnter,在進入前執行,to參數就是當前路由

routes: [
 {
  path: '/home',
  component:() = > import('./home.vue')  //調用的時候再開始加載
  beforeEnter: (to, from, next) => {
   // ...
   next() //正常跳轉,不寫的話,不會跳轉
  }
 }
]
第三種 組件級鉤子函數

主要包括 beforeRouteEnter和beforeRouteUpdate ,beforeRouteLeave,這幾個鉤子都是寫在組件里面也可以傳三個參數(to,from,next),作用與前面類似
1 beforeRouteEnter
在導航確認之前調用,新組件的 beforeCreate 之前調用,所以特別注意它的 this 是 undefined,不過,可以通過傳一個回調給 next來訪問組件實例
2 beforeRouteUpdate
用法:點擊更新二級導航時調用。
3 beforeRouteLeave
離開當前界面之前調用,用法:1. 需要的保存或者刪除的數據沒有完成當前操作等等原因,禁止界面跳轉。

組件鉤子用法和data,methods平級

    data:{},

    methods: {}

  beforeRouteEnter(to, from, next){ // 這個路由鉤子函數比生命周期beforeCreate函數先執行,所以this實例還沒有創建出來
    console.log("beforeRouteEnter")
    console.log(this) //這時this還是undefinde,因為這個時候this實例還沒有創建出來
    next((vm) => { //vm,可以這個vm這個參數來獲取this實例,接著就可以做修改了
      vm.text = '改變了'
    })
  },
  beforeRouteUpdate(to, from, next){//可以解決二級導航時,頁面只渲染一次的問題,也就是導航是否更新了,是否需要更新
    console.log('beforeRouteUpdate')
    next();
  },
  beforeRouteLeave(to, from, next){// 當離開組件時,是否允許離開
    next()
  }

轉載整理https://blog.csdn.net/weixin_41910848/article/details/81697577

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容