1. 程式人生 > 其它 >一文你帶快速認識Vue-Router路由

一文你帶快速認識Vue-Router路由

摘要:Vue Router是Vue.js官方的路由管理器。它和Vue.js的核心深度整合,可以非常方便的用於SPA應用程式的開發。

本文分享自華為雲社群《Vue-Router路由快速瞭解與應用》,原文作者:北極光之夜。

一.速識概念:

1.後端路由:

1.根據不同的使用者URL請求,返回不同的內容,本質上是URL請求地址與伺服器資源之間的對應關係。

2.但是呢,後端渲染存在效能問題。

2.前端路由:

3.所以出現了Ajax前編渲染,前端渲染能提高效能,但是不支援瀏覽器的前進後退操作。

4.這時又出現了SPA(Single Page Application)單頁面應用程式,整個網站只有一個頁面,內容的變化通過Ajax區域性更新實現、同時支援瀏覽器位址列的前進和後退操作。

5.SPA實現原理之一就是基於URL地址的hash(hash的變化會導致瀏覽器記錄訪問歷史的變化、但是hash的變化不會觸發新的URL請求) 。在實現SPA過程中, 其中最核心的技術點就是前端路由。

6.前端路由就是根據不同的使用者事件,顯示不同的頁面內容。本質就是使用者事件與事件處理函式之間的對應關係。

3.Vue Router:

這是官方使用文件連結。:https://router.vuejs.org/zh/guide/#javascript

Vue Router是Vue.js 官方的路由管理器。它和Vue.js的核心深度整合,可以非常方便的用於SPA應用程式的開發。

它的功能如下:

1.支援HTML5歷史模式或hash模式。
2.支援巢狀路由。
3.支援路由引數。
4.支援程式設計式路由。
5.支援命名路由。

二.基本使用:

前提:

下面將會以一個HTML單頁面演示Vue Router的基本使用步驟。在vue專案裡也是一樣的原理。當前單頁面基本程式碼:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0
"> <title>Document</title> </head> <body> <div id="app"> </div> <script> const app = new Vue({ el:"#app", data: {} }) </script> </body> </html>

可以看到什麼都沒有:


下面開始使用的具體步驟:

1.引入相關的檔案:

單頁面肯定得先匯入vue檔案與vue-router檔案,這樣我們才能夠使用路由。

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

2.新增路由連結:

以下是一個vue提供的標籤,預設會被渲染為a標籤。其中有一個to屬性,這個to屬性會被渲染為href屬性,預設值被渲染為 # 開頭的hash地址。簡單來說就是當用戶點選不同時跳轉不同內容,而這個標籤就是使用者要點選的東西,相當於a標籤嘛。

<router-link to="/..." >...</router-link>

給我們的單頁面上加一個page1和一個page2的連結:

<div id="app">
       <router-link to="/page1">Page1</router-link>
       <router-link to="/page2">Page2</router-link>
    </div>

3.新增路由填充位:

下面這個標籤叫路由填充位,就是說未來通過我們的路由規則匹配到的元件,將會被渲染到 router-view所在位置。簡單來說,就是使用者點選路由連結,那得跳轉內容吧,我們知道的是肯定不是整個頁面都跳轉,只是頁面內相關的局部發生內容改變,這個區域性就是router-view所在顯示的區域。

<router-view></router-view>

給我們的頁面新增:

<div id="app">
        <router-link to="/page1">Page1</router-link>
       <router-link to="/page2">Page2</router-link>
       <router-view></router-view>
    </div>

4.定義路由元件:

既然要顯示不同的內容,那肯定是用一個元件儲存一份內容。下面我們給單頁面定義page1,page2這兩個元件。

 <script>
        const Page1 = {
            template: '<h1>我是北極光之夜1號</h1>'
        }
        const Page2 = {
            template: '<h1>我是北極光之夜2號</h1>'
        }
        const app = new Vue({
            el:"#app",
            data: {}
        })
    </script>

5.配置路由規則井建立路由例項:

routes是路由規則陣列。每個路由規則都是一個配置物件, 其中至少包含path 和component 兩個屬性,path 表示當前路由規則匹配的hash 地址,component 表示當前路由規則對應要展示的元件。簡單來說就是你點選那個連結對應的地址要對應的是哪個內容的元件。path跟router-link標籤裡的地址要一樣,別寫錯了。

const router = new VueRouter({
            routes: [
                {path:'/page1',component:Page1 },
                {path:'/page2',component:Page2 }
            ]
        })

6.把路由掛載到Vue根例項中:

為了能夠讓路由規則生效,必須把路由物件掛載到vue 例項物件上。

 const app = new Vue({
            el:"#app",
            data: {},
            router
        })

7.效果與單頁面程式碼:

以上我們就大工告成~


上面的完整程式碼:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 匯入vue檔案 -->
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
    <div id="app">
       <router-link to="/page1">Page1</router-link>
       <router-link to="/page2">Page2</router-link>
       <router-view></router-view>
    </div>
    <script>
        const Page1 = {
            template: '<h1>我是北極光之夜1號</h1>'
        }
        const Page2 = {
            template: '<h1>我是北極光之夜2號</h1>'
        }
        const router = new VueRouter({
            routes: [
                {path:'/page1',component:Page1 },
                {path:'/page2',component:Page2 }
            ]
        })
        const app = new Vue({
            el:"#app",
            data: {},
            router
        })
    </script>
</body>
</html>

三.路由重定向:

路由重定向指的是使用者在訪問地址A的時候,強制使用者跳轉到地址B,從而展示特定的元件頁面。

通過路由規則的redirect屬性,指定一個新的路由地址,可以很方便地設定路由的重定向。

{path:'/..',redirect: '/...'}

其中path表示重定向的原地址,redirect表示新地址。

比如第二大點的案例中,剛開啟的頁面如下,在根目錄,但我們想一進入就顯示page1,那就給根目錄重定向。


修改路由規則如下:

const router = new VueRouter({
            routes: [             
                {path:'/page1',component:Page1 },
                {path:'/page2',component:Page2 },
                {path:'/',redirect:'/page1'}
            ]
        })

看效果,我沒點選就預設進入page1了:

四.巢狀路由:

功能如下:

  1. 點選父級路由連結顯示模板內容。
  2. 模板內容中又有子級路由連結。
  3. 點選子級路由連結顯示子級模板內容。

比如我們改進第二大點的案例,當點選page2顯示page2內容時,page2裡又有兩個子路由連線,star和moon,當點選其中一個連結時又能顯示對應的star或moon內容。

1.首先給page2元件新增兩個子路由連結:

const Page2 = {
            template: `
                 <div>
                 <h1>我是北極光之夜2號</h1>
                 <hr/>
                 <router-link to="/page2/star">Star</router-link>
                 <router-link to="/page2/moon">Moon</router-link>
                 <hr/>
                 </div>`
        }

此時頁面也把顯示子路由連結出來了:

2.給兩個子路由連結新增路由填充位:

const Page2 = {
const Page2 = {
            template: `
                 <div>
                 <h1>我是北極光之夜2號</h1>
                 <hr/>
                 <router-link to="/page2/star">Star</router-link>
                 <router-link to="/page2/moon">Moon</router-link>
                 <hr/>
                 <router-view></router-view>
                 </div>`
        }

3.設定兩個子元件star與moon的內容:

 const Star = {
            template: '<h2>我是北極光之夜2號下的star</h2>'
        }
        const Moon = {
            template: '<h2>我是北極光之夜2號下的Moon</h2>'
        }

4.配置路由規則:

page2的規則除了path和component屬性外,再新增一個children屬性,這個屬性以陣列表示,數組裡存放其子路由的規則,其規則也是一樣的,套娃套娃。

const router = new VueRouter({
            routes: [
                {path:'/page1',component:Page1 },
                {
                    path:'/page2',
                    component:Page2, 
                    children: [
                        {path: '/page2/star',component:Star},
                        {path: '/page2/moon',component:Moon}
                    ]
                }
            ]
        })

5.效果與單頁面程式碼:


完整程式碼:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 匯入vue檔案 -->
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
    <div id="app">
       <router-link to="/page1">Page1</router-link>
       <router-link to="/page2">Page2</router-link>
       <router-view></router-view>
    </div>
    <script>
        const Page1 = {
            template: '<h1>我是北極光之夜1號</h1>'
        }
        const Page2 = {
            template: `
                 <div>
                 <h1>我是北極光之夜2號</h1>
                 <hr/>
                 <router-link to="/page2/star">Star</router-link>
                 <router-link to="/page2/moon">Moon</router-link>
                 <hr/>
                 <router-view></router-view>
                 </div>`
        }
        const Star = {
            template: '<h2>我是北極光之夜2號下的star</h2>'
        }
        const Moon = {
            template: '<h2>我是北極光之夜2號下的Moon</h2>'
        }
        const router = new VueRouter({
            routes: [
                {path:'/page1',component:Page1 },
                {
                    path:'/page2',
                    component:Page2, 
                    children: [
                        {path: '/page2/star',component:Star},
                        {path: '/page2/moon',component:Moon}
                    ]
                }
            ]
        })
        const app = new Vue({
            el:"#app",
            data: {},
            router
        })
    </script>
</body>
</html>

五. 動態路由匹配:

1.動態匹配路由基本使用:

如果某些路由規則的一部分是一樣的,只有另一部分是動態變化的,那我們可以把這些動態變化的部分形成路由引數,這些引數就叫做動態路由匹配。簡單來說,你先看下面這些路由連結,它們都有/page/,就是後面不一樣:

 <router-link to="/page/1">Page1</router-link>
   <router-link to="/page/2">Page2</router-link>
   <router-link to="/page/3">Page3</router-link>

那該咋配置路由呢?這樣嗎:

const router = new VueRouter({
            routes: [
                {path:'/page/1',component:Page},
                {path:'/page/2',component:Page},
                {path:'/page/3',component:Page}
            ]
        })

這樣萬一有很多一個個寫豈不是太麻煩了,所以引入引數,在動態改變的部分定義為引數,引數前面有一個冒號,那上面可簡寫成如下,動態部分設為引數:id。

const router = new VueRouter({
            routes: [
                {path:'/page/:id',component:Page },
            ]
        })

在元件可以通過以下語法獲取當前路由的引數:

$router.params.引數名稱

好,再次修改第二大點的案例完成動態路由匹配:

1.定義路由連結:

<div id="app">
   <router-link to="/page/1">Page1</router-link>
   <router-link to="/page/2">Page2</router-link>
   <router-link to="/page/3">Page3</router-link>
   <router-view></router-view>
   </div>

2.動態配置路由,引數id:

const router = new VueRouter({
    routes: [
        {path:'/page/:id',component:Page1 },
    ]
})

3.設定元件內容,並顯示當前路由的引數:

const Page1 = {
    template: '<h1>我是北極光之夜1號,當前id為:{{$route.params.id}}</h1>'
}

看效果:

2.路由元件傳參:

上面的$route與對應路由形成高度耦合,不夠靈活啊,所以可以使用props將元件和路由解耦。簡單來說,好像也沒什麼說的,直接看下面例項就能理解了。

2.1 當props為布林型別:

  const router = new VueRouter({
            routes: [
 // 設定props,如果props為true,router.params會被設定為元件屬性
                {path:'/page/:id',component:Page1,props: true },
            ]
        })  
              
        const Page1 = {
// 這時就通過props接收引數,快速簡潔的接收引數id和使用它
                    props: ['id'],
                    template: '<h1>我是北極光之夜1號,當前id為:{{id}}</h1>'
                }

能達到一樣的效果,且更靈活了,上面記得反過來,先定義元件才配置路由規則,只是為了直觀才這樣寫:

2.2 當props為物件型別:

   const Page1 = {
        // 這時就通過props接收引數,快速簡潔的接收引數物件 並顯示
                props: ['name','age'],
                template: `<h1>我是北極光之夜1號,當前id為:{{id}}
                            <hr/>
                           姓名為:{{name}} ,年齡為:{{age}} </h1>`
                }
             const router = new VueRouter({
                routes: [
            // props為一個引數物件,它會原樣設定為元件屬性,
            // 裡面的自定義的引數都能傳過去,但是id傳不了了
                    {path:'/page/:id',component:Page1 , props: {name:'auroras',age: 18} }
                ]
             })  

效果,物件props物件裡的能獲取,id就不行了:

2.3 當props為函式型別:

這個就什麼都能獲取。

    const Page1 = {
// 這時就通過props接收引數,快速簡潔的接收引數
        props: ['name','age','id'],
        template: `<h1>我是北極光之夜1號,當前id為:{{id}}
                    <hr/>
                   姓名為:{{name}} ,年齡為:{{age}} </h1>`
        }
     const router = new VueRouter({
        routes: [
    // props為函式,這個物件接收router物件為自己形參,
    // 裡面的自定義的引數和id都能傳過去
            {path:'/page/:id',
            component:Page1 , 
            props: router => ({id: router.params.id,name:'auroras',age: 18}) }
        ]
     })  

效果:


當前完整程式碼:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 匯入vue檔案 -->
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
    <div id="app">
        <router-link to="/page/1">Page1</router-link>
        <router-link to="/page/2">Page2</router-link>
        <router-link to="/page/3">Page3</router-link>
        <router-view></router-view>
        </div>   
         <script>
            const Page1 = {
        // 這時就通過props接收引數,快速簡潔的接收引數物件 
                props: ['name','age','id'],
                template: `<h1>我是北極光之夜1號,當前id為:{{id}}
                            <hr/>
                           姓名為:{{name}} ,年齡為:{{age}} </h1>`
                }
             const router = new VueRouter({
                routes: [
            // props為函式,這個物件接收router物件為自己形參,
            // 裡面的自定義的引數和id都能傳過去
                    {path:'/page/:id',
                    component:Page1 , 
                    props: router => ({id: router.params.id,name:'auroras',age: 18}) }
                ]
             })  
        const app = new Vue({
            el:"#app",
            data: {},
            router
        })
    </script>
</body>
</html>

六.Vue-Router命名路由:

為更加方便的表示路由的路徑,可以給路由規則起一個別名, 即為“命名路由”。繼續改進上面的案例講解用法:

1.首先給路由規則加一個name屬性,這個就是別名:

 const router = new VueRouter({
    routes: [
        {
        name: 'user',
        path:'/page/:id',
        component:Page1 , 
        props: router => ({id: router.params.id,name:'auroras',age: 18}) }
    ]
 }) 

2.在路由連結中使用:

  <div id="app">
    <router-link :to="{name:'user',params: {id: 1}}">Page1</router-link>
    <router-link to="/page/2">Page2</router-link>
    <router-link to="/page/3">Page3</router-link>
    <router-view></router-view>
    </div>   

我們把第一個路由連結改進,to前面加上冒號,其中name表示匹配的是哪個路由規則,params表示要傳遞的引數,看下面是一樣的效果:

七.程式設計式導航:

  1. 宣告式導航:首先宣告式導航是指使用者通過點選連結完成導航的方式,比如點選a標籤或者路由連結這些完成的跳轉。
  2. 程式設計式導航:程式設計式導航就是說跳轉是因為我點選它,它不是連結,但是它在JavaScript裡呼叫了某個API也實現了跳轉。
  3. 常用的程式設計式導航API如下:
this.$router.push('要跳轉的hash地址')
this.$router.go(n)

push裡直接放要跳轉的雜湊地址,go方法實現前進和後退,n代表陣列,若n為1代表在歷史記錄中前進一位,-1代表在歷史記錄中後退一位。

1. this.$router.push(’ '):

重寫一個案例,有page1、page2、page3三個路由連結,而在page3裡有一個按鈕,這個按鈕的作用是點選後返回顯示page1的內容。這個按鈕可不是宣告式導航裡的連結,就是一個按鈕。

1.定義普通的路由連結:

 <div id="app">
    <router-link :to="/page/1">Page1</router-link>
    <router-link to="/page/2">Page2</router-link>
    <router-link to="/page/3">Page3</router-link>
    <router-view></router-view>
    </div> 

2.定義3個元件內容,其中給page3元件裡放一個按鈕,並繫結點選事件,在事件裡通過API導航到page1:

const Page1 = {
    template: `<h1>我是北極光之夜1號</h1>`
}
const Page2 = {
    template: `<h1>我是北極光之夜2號</h1>`
}
const Page3 = {
    template: `<div>
            <h1>我是北極光之夜3號</h1>
            <button @click="goPage1">返回page1</button>
               </div>`,
    methods: {
        goPage1(){
            this.$router.push('/page/1')
        }
    },
    
}

3.路由規則:

const router = new VueRouter({
                routes: [
                    {path:'/page/1',component: Page1},
                    {path:'/page/2',component: Page2},
                    {path:'/page/3',component: Page3}
                ]
             })  

4.看效果:


5.完整程式碼:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 匯入vue檔案 -->
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
    <div id="app">
        <router-link to="/page/1">Page1</router-link>
        <router-link to="/page/2">Page2</router-link>
        <router-link to="/page/3">Page3</router-link>
        <router-view></router-view>
    </div>   
         <script>
            const Page1 = {
                template: `<h1>我是北極光之夜1號</h1>`
            }
            const Page2 = {
                template: `<h1>我是北極光之夜2號</h1>`
            }
            const Page3 = {
                template: `<div>
                        <h1>我是北極光之夜3號</h1>
                        <button @click="goPage1">返回page1</button>
                           </div>`,
                methods: {
                    goPage1(){
                        this.$router.push('/page/1')
                    }
                },
                
            }
             const router = new VueRouter({
                routes: [
                    {path:'/page/1',component: Page1},
                    {path:'/page/2',component: Page2},
                    {path:'/page/3',component: Page3}
                ]
             })  

        const app = new Vue({
            el:"#app",
            data: {},
            router
        })
    </script>
</body>
</html>

不止href路徑,還可以有以下操作:

//字串形式(路徑的名稱)
router.push('/page1')
//物件的形式
router.push({path: '/page1'})
//也可以傳遞引數,命名的路由
router.push({name: '/page1',parmas:{id: 1}})
//帶查詢引數,變成  /page1?p=id 
//這個挺實用的,比如在某些音樂網頁,點選歌單後要導航到另一個該歌單詳細介面,此時要帶id,詳細介面靠此id重新發送請求,請求詳細資訊
router.push({parh: '/page1',query:{p: 'id' }})

2. this.$router.go(n):

改進第1小點的案例,當我page3跳到page1時,page1裡又有一個返回的按鈕。我們把n設定為-1,他就會在歷史記錄中後退一位,後退一位就是page3.
修改page1元件內容:

const Page1 = {
                template: `<div>
                        <h1>我是北極光之夜1號</h1>
                        <button @click="goBack">返回</button>
                           </div>`,
                  methods: {
                    goBack(){
                        this.$router.go(-1)
                    }
            }
        }

效果:

點選關注,第一時間瞭解華為雲新鮮技術~