1. 程式人生 > >vue2.X基礎知識八之vue-router路由

vue2.X基礎知識八之vue-router路由

  前端路由是直接找到與地址匹配的一個元件或物件並將其渲染出來。改變瀏覽器地址而不向伺服器發出請求有兩種做法,一是在地址中加入#以欺騙瀏覽器,地址的改變是由於正在進行頁內導航;二是使用HTML5的window.history功能,使用URL的Hash來模擬一個完整的URL。將單頁程式分割為各自功能合理的元件或者頁面,路由起到了一個非常重要的作用。它就是連線單頁程式中各頁面之間的鏈條。

一、在vue中引入vue-router

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

二、路由配置

  Vue.js是沒有頁面這個概念的,Vue.js的容器就只有元件。但我們用vue-router配合元件又會重新形成各種的"頁面",我們可以這樣來約定和理解:

  1. 頁面是一個抽象的邏輯概念,用於劃分功能場景
  2. 元件是頁面在Vue的具體實現方式

vue-router提供了兩個指令標籤元件來處理這個導航與自動渲染邏輯:

  • <router-view>——渲染路徑匹配的檢視元件,它還可以內嵌自己的<router-view>,根據巢狀路徑渲染巢狀元件。
  • <router-link>——支援使用者再具有路由功能的應用中(點選)導航

   例如,這裡有三個router-link連結

const App = {
  template: ·<ul>
       <li>
	<router-link to="/a">a</router-link>
          <ul>
          <li>
              <router-link to="/a/aa">aa</router-link>
          </li>
        </ul>
     </li>
   </ul>·

}
const a = {
    template: `<div>這裡是a
              // 這裡是子路由aa顯示的地方
              <router-view></router-view>		
    	       </div>`
};

const aa = {
	  template: `<div>這裡是a下面的子路由aa{{ $route.params }}</div>`
};

定義a路由及其子路由aa:

const router = new VueRouter({
    routes: [
    {
    	path: '/a',
    	component: a,
    	// 子路由不需要'/'
    	// 子路由顯示的地方 父級路由模板裡的第一個 router-view 標籤裡
    	children: [{
    		path: 'aa',
    		component: aa
    	}]
    }]
})


vue-router提供了一種隱式的路由引用方式,vue-router將之稱為"命名路由",簡單點說就是通過路由的名稱引用取代URL的直接引用。如下所示:

const router = new VueRouter({
  routes: [
    {name: 'Home', path: '/', component: Home},
    {
     name: 'Me', path: '/me', component: Me
    }
  ]

})

在<router-link>內通過名稱引用路由需要向to屬性傳入一個物件顯式宣告路由的名稱:

<router-link :to="{name: 'Home'}">

使用命名路由引用時採用的是:to 而不是to, 因為這個時候向<router-link>傳入的是一個物件{name:'Home'}而不是字串。

三、輸出指定元素

<router-link>元件支援使用者在具有路由功能的應用中(點選)導航。通過to屬性指定目標地址,預設渲染成帶有正確連結的<a>標籤。其實,我們並不需要輸出<a>元素標記,因為我們並沒有具體的連結地址,使用<li>元素同樣可以處理來自使用者的點選切換路由的事件。<router-link>可以通過配置tag屬性生成別的標籤,利用這個屬性我們可以直接輸出<li>而節省更多的程式碼:

<router-link :to="{ name: 'Home' }" tag="li"></router-link>

四、動態路由

將引數融入到路由的路徑定義之內成為路徑的一部分,是之更具有可讀性,我們稱這種引數為"動態路徑引數",具體的做法是在引數名之前加上“:”,然後將引數寫在路由的path內,具體定義如下:

routes: [
  {
    name: 'BookDetails',
    // 這裡的 :id 就是動態路徑引數
    path: '/books/:id',
    component: BookDetails
  }
]

在<router-link>中我們就可以加入一個params的屬性來指定具體的引數值:

<router-link :to="{name: 'BookDetails', params: { id: 1}}">
</router-link>

在元件中獲取這個id:

export default {
  created () {
    const bookID = this.$route.params.id
  }
}
當使用路由引數時,例如從/books/1 導航到 /books/2,原來的元件例項會被複用。因為兩個路由都渲染同一個元件,比起銷燬再建立,複用顯得更加高效。不過,這也意味著元件的生命週期鉤子不會再被呼叫,也就是created、mounted等鉤子函式再頁面第二次載入時將失效。那麼,當複用元件時,想對路由引數的變化做出響應的話,就需要再watch物件內新增對$route物件變化的跟蹤函式:
export default {
  template: '',
  watch: {
    '$route' (to, from) {
      //  對路由變化作出響應
    }
  }
}

$route.params定義的引數必然是整個路由的其中一個部分,vue-router還可以讓我們使用"/path?引數=值"的方式,也就是俗稱的查詢字串傳遞資料。如果要從$route中讀取Query string的引數,可以使用$route.query引數名的方式讀取。

<div>
    <router-link :to="{ path: '/b', query: { id: 123 }}">/b/bb</router-link>
</div>
const b = Vue.component('b', {
	  template: `<div>這裡是b</div>`,
	  mounted () {
	  	console.log(this.$route.query);
	  }
});

五、切頁動效

使用Vue提供的<transition></transition>封裝元件可以給任何元素和元件新增進入和退出的過渡效果。

有4個css類名在enter/leave的過渡中切換,以下是這4個類名的命名規則和作用。

  • CSS類名-enter:定義進入過渡的開始狀態。在元素被插入時生效,在下一幀移除。
  • CSS類名-enter-active: 定義進入過渡的結束狀態。在元素被插入時生效,在transition/animation完成之後移除。
  • CSS類名-leave: 定義離開過渡的開始狀態。在離開過度被觸發時生效,在一個幀移除。
  • CSS類名-leave-active: 定義離開過渡的結束狀態。在離開過渡被觸發時生效,在transition/animation完成之後移除。
<template>
  <transition name="slide-fade">
    <router-view></router-view>
  </transition>
</template>
.slide-fade-enter-active {
  transition: all .3s ease
}
.slide-fade-leave-active {
  transition: all .3s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter,
.slide-fade-leave-active {
  transform: translateX(-430px)
  opacity: 0
}

六、導航狀態樣式

在預設情況下當<router-link>對應的路由匹配成功時,就會自動設定class屬性值為.router-link-active,如果我們想要將“啟用”狀態樣式類命名為active,可以通過active-class屬性進行設定,例如:

<router-link :to="{ name: 'Home' }" tag="li" active-class="active">
    <div>
        <img src="xxx">
    </div>
</router-link>

如果在頁面上都是這麼顯式宣告,那麼就需要在每個<router-link></router-link>元件元素上都要寫一次;我們還可以有另外一個選擇,就是在VueRouter的全域性配置上進行宣告,直接將.router-link-active這個預設值改為active,在main.js檔案內的VueRouter配置中加入以下語句:

const router = new VueRouter({
    linkActiveClass: "active"
});

通過linkActiveClass全域性屬性就能進行統一的設定了。

6.1、精確匹配與包含匹配

<router-link>新增“啟用”狀態樣式類的預設依據是對URL地址的全包含匹配。舉個例子,如果當前的路徑是/home,那麼<router-link to="/">也會被匹配並設定CSS類名。

想要連結使用“精確匹配模式”,則使用exact屬性。在上面的例子中,“Home”路由就必須以精確匹配模式,否則它的tab被點選中之後,Home的tab會始終保持“啟用”狀態。

<!-- 這個連結只會在地址為/的時候被啟用 -->
<router-link :to="{name: 'Home'}" exact>

七、History的控制

當我們使用HTML5的History模式的時候,每次路由的改變都會被"推"到導航歷史中保留,在某些情況下我們不需要瀏覽器這樣做,而是希望它能將原有的記錄進行替換,那麼我們據需要了解<router-link>是如何通過程式設計方式控制路由進行導航的。首先Vue例項內有一個$router物件,這個物件會提供三個方法,<router-link>則是用兩種屬性來對應這三個方法的呼叫:

router的方法屬性說明
push()-預設呼叫此方法
append()append將目標URL追加到當前URL
replace()replace以目標URL替換現有的URL

設定replace屬性的話,當點選時,會呼叫router.replace()而不是router.push(),於是導航後不會留下History記錄。

<router-link :to="{ name: 'Home'}" replace></router-link>

設定append屬性後,則在當前(相對)路徑前新增基路徑。例如,我們從/a導航到一個相對路徑b,如果沒有配置append,則路徑為/b,如果配置了,則為/a/b。

<router-link :to="{ path: 'relative/path'}" append></router-link>

八、關於Fallback

如果將路由配置為History模式,假如使用者點選Home上的<router-link>時,瀏覽器的位址列就會自動改變成對應的URL。如果我們直接在瀏覽器輸入http://localhost/home,你會驚奇的發現瀏覽器會出現404的錯誤!

這是由於直接在瀏覽器輸入http://localhost/home,瀏覽器就會直接將這個地址請求傳送至伺服器,先由伺服器處理路由,而客戶端路由的啟動條件是要訪問/index.html,所以,客戶端路由完全失效了!

解決的辦法是將所有發到伺服器的請求利用服務端的URLRewrite模板重新轉發給/index.html,啟動VueRouter進行處理,而瀏覽器位址列的URL保持不變。

當我們部署到生產環境時,就需要在web伺服器進行一些簡單配置以支援Fallback了。

Nginx

當出現404時將自動重定向至index.html

location / {
  try_files $uri $uri/ /index.html;
}
本文內容摘抄自《vue2實踐揭祕》