【前端 Vue】07 - Vue-router

1. 后端路由階段

早期的網站開發整個HTML頁面是由服務器來渲染的。服務器直接生產渲染好對應的HTML頁面, 返回給客戶端進行展示。

1.1 但是, 一個網站, 這么多頁面服務器如何處理呢?

  1. 一個頁面有自己對應的網址, 也就是URL

  2. URL會發送到服務器, 服務器會通過正則對該URL進行匹配, 并且最后交給一個Controller進行處理。

  3. Controller進行各種處理, 最終生成HTML或者數據, 返回給前端。

  4. 這就完成了一個IO操作。

上面的這種操作, 就是后端路由,當我們頁面中需要請求不同的路徑內容時, 交給服務器來進行處理, 服務器渲染好整個頁面, 并且將頁面返回給客戶端,這種情況下渲染好的頁面, 不需要單獨加載任何的jscss, 可以直接交給瀏覽器展示, 這樣也有利于SEO的優化。

1.2 后端路由的缺點:

  1. 一種情況是整個頁面的模塊由后端人員來編寫和維護的;

  2. 另一種情況是前端開發人員如果要開發頁面, 需要通過PHPJava等語言來編寫頁面代碼;

  3. 而且通常情況下HTML代碼和數據以及對應的邏輯會混在一起, 編寫和維護都是非常糟糕的事情。

2. 前端路由階段

2.1 前后端分離階段

  1. 隨著Ajax的出現, 有了前后端分離的開發模式。

  2. 后端只提供API來返回數據, 前端通過Ajax獲取數據, 并且可以通過JavaScript將數據渲染到頁面中。

  3. 這樣做最大的優點就是前后端責任的清晰, 后端專注于數據上, 前端專注于交互和可視化上。

  4. 并且當移動端(iOS/Android)出現后, 后端不需要進行任何處理, 依然使用之前的一套API即可。

2.2 單頁面富應用階段

  1. 其實SPA最主要的特點就是在前后端分離的基礎上加了一層前端路由。

  2. 也就是前端來維護一套路由規則。

3. URL的hash 模式 和 HTML5 的 history 模式

3.1 URL的hash模式

  1. URLhash也就是錨點(#), 本質上是改變window.locationhref屬性;我們可以通過直接賦值location.hash來改變href, 但是頁面不發生刷新。
location.hash改變location的href屬性
地址欄是這樣的

3.2 HTML5的history模式

  1. history對象的pushState方法傳遞三個參數,第一個參數是一個對象。第二個參數是title , 第三個參數是路徑。
pushState方法
地址欄是這樣的
  1. history模式的replaceState方法:替換路徑,不能通過返回箭頭返回。
history的replaceState方法
  1. history模式的go方法:到某個索引的路徑下:
history.go(-1) // 表示后退一步  和 history.back() 類似 

history.go(1) // 表示前進一步 和 history.forward() 類似

4. Vue-Router的安裝配置

  1. Vue-router是 Vue.js官方的路由插件,它和

4.1 安裝 Vue-Router

  1. 安裝為一個運行時依賴:
npm install vue-router --save 
  1. 創建一個router文件夾,并在文件中創建一個index.js文件。

  2. index.js文件中引入 VueRouter對象和 Vue對象。

import VueRouter from 'vue-router';
import Vue from 'vue';
  1. 通過Vue.use(傳入插件)安裝該插件,任何Vue的插件都要使用 Vue.use進行安裝。
Vue.use(VueRouter);
  1. 創建 VueRouter對象實例注意這里是 routes 而不是 routers 重要重要重要
// 路由數組
const routes = [];

// 2. 創建VueRouter對象
const router = new VueRouter({
  // 配置組件之間的映射關系
  // 對象屬性的簡寫
  routes
});
  1. 導出 VueRouter對象實例:
export default router;
  1. main.js中引入并使用 router
在`main.js`中引入并使用 `router`

4.2 配置路由的映射關系

  1. components文件夾下創建 HomeAbout組件。
  1. router/index.js下配置路由映射關系 。
配置路由映射關系
  1. 使用 Vue 中注冊的全局組件 router-linkrouter-view實現頁面跳轉和渲染。
 <div id="app">
    <!-- router-link是Vue中注冊的全局組件 -->
    <router-link to="/home">首頁</router-link>
    <router-link to="/about">關于</router-link>
    <router-view></router-view>
  </div>
  1. <router-link>: 該標簽是一個vue-router中已經內置的組件, 它會被渲染成一個<a>標簽。

  2. <router-view>: 該標簽會根據當前的路徑, 動態渲染出不同的組件。

  3. 默認顯示首頁:/home,將進入頁面時將頁面重定向到 Home頁面

// 路由數組
const routes = [
  {
    path: '/',
    /* 將路徑重定向到home */
    redirect: '/home'
  },
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    component: About
  }
]

4.3 修改路由的模式為 history

  1. 默認情況下,路徑改變使用的是URLhash,如果希望使用 HTML5history模式可以進行如下的修改。
修改路由的模式為history
// 2. 創建VueRouter對象
const router = new VueRouter({
  // 配置組件之間的映射關系
  // 對象屬性的簡寫 但是這個屬性必須交 routes
  routes,
  mode:'history'
});

4.4 router-link 的其他屬性

router-link 標簽的 tag 屬性
  1. 可以 通過 tag設置router-link使用什么標簽來進行渲染。
<!-- router-link是Vue中注冊的全局組件 -->
    <router-link tag="button" to="/home">首頁</router-link>
    <router-link tag="button" to="/about">關于</router-link>
使用button標簽進行渲染
router-link 標簽的 replace 屬性
  1. replace屬性設置之之后通過該標簽跳轉的路徑,不能通過瀏覽器的后退鍵返回。replace不會留下history記錄, 所以指定replace的情況下, 后退鍵返回不能返回到上一個頁面中。這就說明vue-router默認使用的是 historypushState
<!-- router-link是Vue中注冊的全局組件 -->
    <router-link tag="button" to="/home" replace>首頁</router-link>
    <router-link tag="button" to="/about" replace>關于</router-link>
不能通過瀏覽器的后退鍵返回
router-link 標簽的 active-class 屬性
  1. 默認情況下當點擊某個標簽,該標簽被激活之后,在其中會添加一個classrouter-link-active。可以通過該class設置激活樣式。
 .router-link-active {
    color: #f00;
  }
按鈕被激活
  1. class的名稱是可以被修改的,此時就需要在標簽中 使用active-class屬性對class的名稱進行修改。
    <!-- router-link是Vue中注冊的全局組件 -->
    <router-link tag="button" to="/home" replace active-class="active">首頁</router-link>
    <router-link tag="button" to="/about" replace active-class="active">關于</router-link>
.active {
    color: #00f;
  }
使用active-class修改class的名稱
router/index.js文件的router對象中使用linkActiveClass屬性統一修改樣式名稱
統一對link激活樣式名稱進行修改
統一修改了link的樣式名稱
將link的激活樣式名稱修改為linkActive

4.5 通過代碼實現路由的跳轉

  1. 在頁面中定義兩個按鈕實現路由的跳轉:利用 vue內置的 $routerpushreplace方法實現跳轉。
    <!-- 通過代碼實現路由的跳轉  -->
    <button @click="btnClickHome">首頁</button>
    <button @click="btnClickAbout">關于</button>
      /**
       * 跳轉到 首頁
       */
      btnClickHome() {
        // this.$router.push('/home');
        this.$router.replace('/home'); // 跳轉之后不能通過瀏覽器的后退按鈕返回
      },

      /**
       * 實現跳轉到關于
       */
      btnClickAbout() {
        // this.$router.push('/about');
        this.$router.replace('/about'); // 跳轉之后不能通過瀏覽器的后退按鈕返回
      }

5. vue-router 動態路由的使用

  1. 創建一個 User組件并在 router/index.js中配置路由:

// 路由數組
const routes = [
  {
    path: '/',
    /* 將路徑重定向到home */
    redirect: '/home'
  },
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    component: About
  },
  {
    path: '/user/:userId',
    component: User
  }
];
配置User組件的路由
  1. APP.vue中使用 router-link配置路由實現跳轉:在配置時一并傳遞參數。
     <!-- 實現動態路由 -->
    <router-link to="/home">首頁</router-link>
    <router-link to="/about">關于</router-link>
    <!-- 在此使用動態路由 使用 v-bind 動態綁定 -->
    <router-link :to="`/user/` + userId">用戶</router-link>
使用v-bind動態綁定userId
  1. 在跳轉到User組件之后,在User頁面獲取到路徑中的userId參數:這里需要通過一個$route的屬性獲取。使用 $route.params.userId獲取。但是這里的userId是與路由配置中的userId一一對應的。
 <div>
    <h2>我是User組件</h2>
    <!-- 獲取到路徑中傳遞的用戶名 的兩種方式-->
    <!-- 1. 直接在Mustache語法中寫 -->
    <h2>{{$route.params.userId}} 您好!</h2>
    <!-- 2. 通過計算屬性的方式 -->
    <h2>{{userId}} 您好!</h2>
  </div>
computed: {
      userId() {
        return this.$route.params.userId
      }
    }
通過$route.params.userId獲取路徑中userId參數

6. vue-router 打包文件的解析

打包之后的dist文件夾下的JS

7. 路由的懶加載

  1. 路由懶加載的官方解釋:首先, 我們知道路由中通常會定義很多不同的頁面,這個頁面最后被打包在哪里呢? 一般情況下, 是放在一個js文件中,但是, 頁面這么多放在一個js文件中, 必然會造成這個頁面非常的大,
    如果我們一次性從服務器請求下來這個頁面, 可能需要花費一定的時間, 甚至用戶的電腦上還出現了短暫空白的情況。

  2. 路由懶加載做了什么? 答: 路由懶加載的主要作用就是將路由對應的組件打包成一個個的js代碼塊。只有在這個路由被訪問到的時候, 才加載對應的組件。

配置路由懶加載前后

7.2 各種路由懶加載的配置方式

  1. 方式一: 結合Vue的異步組件和Webpack的代碼分析
const Home = resolve => { require.ensure(['../components/Home.vue'], () => { resolve(require('../components/Home.vue')) })};
  1. 方式二:AMD寫法
const About = resolve => require(['../components/About.vue'], resolve);
  1. 方式三: 在ES6中, 我們可以有更加簡單的寫法來組織Vue異步組件和Webpack的代碼分割
const Home = () => import('../components/Home.vue')

8. 認識路由的嵌套

理解路由的嵌套

8.1 嵌套路由配置案例

  1. 創建一個 HomeMessageHomeNews組件。
<template>
  <div>
    <ul>
      <li>消息1</li>
      <li>消息2</li>
      <li>消息3</li>
      <li>消息4</li>
    </ul>
  </div>
</template>

<script>
    export default {
        name: "home-message"
    }
</script>

<style scoped>

</style>
<template>
  <div>
    <ul>
      <li>新聞1</li>
      <li>新聞2</li>
      <li>新聞3</li>
      <li>新聞4</li>
    </ul>
  </div>
</template>

<script>
    export default {
        name: "home-news"
    }
</script>

<style scoped>
</style>
  1. 配置嵌套路由 :
/* 使用懶加載的方式加載組件 */
const Home = () => import('../components/Home')
const HomeNews = () => import('../components/HomeNews')
const HomeMessage = () => import('../components/HomeMessage')
const About = () => import('../components/About')
const User = () => import('../components/User')

// 1. 通過Vue.use(傳入插件)安裝該插件,任何Vue的插件都要使用 Vue.use進行安裝
Vue.use(VueRouter);

// 路由數組
const routes = [
  {
    path: '/',
    /* 將路徑重定向到home */
    redirect: '/home'
  },
  {
    path: '/home',
    name: 'Home',
    component: Home,
    /* 配置路由的嵌套 */
    children:[
      /* 配置默認顯示首頁的時候一并顯示消息 */
      {
        path:'/',
        redirect:'news'
      }
      ,
      {
        /* 注意這里沒有 斜杠 / 這里是不能有 斜杠的  */
        path:'news',
        component:HomeNews
      },
      {
        path:'message',
        component:HomeMessage
      }
    ]
  },
  {
    path: '/about',
    component: About
  },
  {
    path: '/user/:userId',
    component: User
  }
];
嵌套路由的詳細配置
  1. 因為這兩個組件需要在 Home組件中切換顯示,所以還需在Home組件中使用router-linkrouter-view進行配置。
<template>
  <div>
    <h2>我是Home組件</h2>
    <router-link to="/home/news">新聞</router-link>
    <router-link to="/home/message">消息</router-link>
    <router-view></router-view>
  </div>
</template>
在Home組件中使用 router-link 和 router-view進行配置

9. vue-router 參數傳遞

9.1 參數傳遞的方式一 user/:userId

使用在路由中配置的方式傳遞參數

9.2 參數傳遞的方式二 query參數對象傳遞案例

  1. 創建一個新的組件 Profile
<template>
  <div>
    <h2>我是Profile組件</h2>
  </div>
</template>

<script>
  export default {
    name: "profile"
  }
</script>

<style scoped>

</style>
  1. 為組件配置路由 :
為Profile組件配置路由
  1. 使用 router-link的方式實現路由的跳轉并傳遞query參數對象。
使用 `router-link`的方式實現路由的跳轉并傳遞`query`參數對象
  1. 使用觸發事件的方式實現路由的跳轉:通過this.$router.push(``)的方式實現路由跳轉。
使用觸發事件的方式實現路由的跳轉

10. vue-router 和 vue-route 是由區別的

  1. $routerVueRouter實例,想要導航到不同URL,則使用$router.push方法。

  2. $route為當前router跳轉對象里面可以獲取name、path、query、params等。

vue-router和 vue-route是由區別的

11. 導航守衛

1.有時可能需要在跳轉過程之間做一些新的操作。就可以使用導航守衛監聽跳轉過程。

  1. URL組成: URL= scheme(協議)://host(主機):port(端口)/path(路徑)?query(查詢)#fragment(片段)

11.1 當頁面跳轉的時候如果需要改變 title 該如何做?

  1. 網頁標題是通過<title>來顯示的, 但是SPA只有一個固定的HTML, 切換不同的頁面時, 標題并不會改變。

  2. 但是我們可以通過JavaScript來修改<title>的內容 window.document.title = '新的標題'

  1. 那么在Vue 項目中, 在哪里修改? 什么時候修改比較合適呢?
使用導航守衛在路由跳轉前進行修改頁面 title操作
  1. 使用 router實例對象的beforeEach 方法前置守衛函數,函數中傳遞一個鉤子函數,鉤子函數需要 3 個參數。to , from ,next。需要向下執行就需要調用 next()

  2. 在執行next()之前將 title進行修改。但是動態的 title從哪里來呢?

在每一個route中定義一個meta元數據存放title

11.2 導航守衛的分類

  1. 全局路由守衛;

  2. 路由獨享守衛;

  3. 組件內守衛。

  4. 參考

12. vue-router 的 keep-alive

  1. keep-alive 是一個標簽,是一個保持組件為活躍狀態,不會被頻繁的創建和頻繁的銷毀。
保持組件為活躍狀態不會被頻繁的創建和銷毀

12.1 利用 keep-alive 和 activated 、beforeRouteLeave 導航守衛實現記住上一個頁面的選擇案例

keep-alive實現記住上一次
默認home路徑
  1. router-view標簽外面包裹了keep-alive標簽之后 activated方法就會有效:在該方法中實現路由的跳轉。
在`router-view`標簽外面包裹了`keep-alive`標簽
  1. 當離開當前的組件之前記錄一下當前的路徑path
    在beforeRouteLeave方法中就是離開組件之前記住上次的路徑
只有使用 keep-alive標簽包裹的組件使用 activated 和 deactived 才是有效的。

12.2 keep-alive的其他屬性

keep-aliveVue 內置的一個組件,可以使被包含的組件保留狀態,或避免重新渲染。
  1. include : 字符串或正則表達,只有匹配的組件會被緩存;

  2. exclude : 字符串或正則表達式,任何匹配的組件都不會被緩存;

    <!-- 但是中間不要隨便加空格 -->
    <keep-alive exclude="profile,User">
      <router-view></router-view>
    </keep-alive>
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容