1. 程式人生 > 其它 >VUE進階 筆記壹章 前端路由

VUE進階 筆記壹章 前端路由

技術標籤:前端vue

1.路由的基本概念與原理

1.1 路由

路由是一個比較廣義和抽象的概念,路由的本質就是對應關係。在開發中,路由分為:後端路由 和 前端路由。

1.1.1 後端路由

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

1.1.2 SPA(Single Page Application)

  • 後端渲染(存在效能問題)。
  • Ajax前端渲染(前端渲染提高效能,但是不支援瀏覽器的前進後退操作)。
  • SPA(Single Page Application)單頁面應用程式:整個網站只有一個頁面,內容的變化通過Ajax區域性更新實現、同時支援瀏覽器位址列的前進和後退操作。
  • SPA實現原理之一:基於URL地址的hash(hash的變化會導致瀏覽器記錄訪問歷史的變化、但是hash的變化不會觸發新的URL請求)。
  • 在實現SPA過程中,最核心的技術點就是前端路由。

1.1.3 前端路由

概念:根據不同的使用者事件,顯示不同的頁面內容。
本質:使用者事件與事件處理函式之間的對應關係。
在這裡插入圖片描述

1.1.4 實現簡易前端路由

基於URL中的hash實現(點選選單的時候改變URL的hash,根據hash的變化控制組件的切換)。
在這裡插入圖片描述

      // 監聽 window 的 onhashchange 事件,根據獲取到的最新的 hash 值,切換要顯示的元件的名稱
      window.onhashchange
= function () { // 通過 location.hash 獲取到最新的 hash 值 };
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv
="X-UA-Compatible" content="ie=edge" />
<title>Document</title> <!-- 匯入 vue 檔案 --> <script src="./lib/vue_2.5.22.js"></script> </head> <body> <!-- 被 vue 例項控制的 div 區域 --> <div id="app"> <!-- 切換元件的超連結 --> <a href="#/zhuye">主頁</a> <a href="#/keji">科技</a> <a href="#/caijing">財經</a> <a href="#/yule">娛樂</a> <!-- 根據 :is 屬性指定的元件名稱,把對應的元件渲染到 component 標籤所在的位置 --> <!-- 可以把 component 標籤當做是【元件的佔位符】 --> <component :is="comName"></component> </div> <script> // #region 定義需要被切換的 4 個元件 // 主頁元件 const zhuye = { template: "<h1>主頁資訊</h1>", }; // 科技元件 const keji = { template: "<h1>科技資訊</h1>", }; // 財經元件 const caijing = { template: "<h1>財經資訊</h1>", }; // 娛樂元件 const yule = { template: "<h1>娛樂資訊</h1>", }; // #endregion // #region vue 例項物件 const vm = new Vue({ el: "#app", data: { comName: "zhuye", }, // 註冊私有元件 components: { zhuye, keji, caijing, yule, }, }); // #endregion // 監聽 window 的 onhashchange 事件,根據獲取到的最新的 hash 值,切換要顯示的元件的名稱 window.onhashchange = function () { // 通過 location.hash 獲取到最新的 hash 值 console.log(location.hash); switch (location.hash.slice(1)) { case "/zhuye": vm.comName = "zhuye"; break; case "/keji": vm.comName = "keji"; break; case "/caijing": vm.comName = "caijing"; break; case "/yule": vm.comName = "yule"; break; } }; </script> </body> </html>

1.2 Vue Router

Vue Router(官網:https://router.vuejs.org/zh/)是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度整合,可以非常方便的用於SPA應用程式的開發。

Vue Router 包含的功能有:

  • 支援HTML5 歷史模式或 hash 模式 。
  • 支援巢狀路由。
  • 支援路由引數。
  • 支援程式設計式路由。
  • 支援命名路由。

2. vue-router的基本使用

2.1 基本使用步驟

  1. 引入相關的庫檔案;
  2. 新增路由連結;
  3. 新增路由填充位;
  4. 定義路由元件;
  5. 配置路由規則並建立路由例項;
  6. 把路由掛載到 Vue 根例項中。

2.1.1 引入相關的庫檔案

    <!-- 匯入 vue 檔案,為全域性 window 物件掛載 Vue 建構函式 --> 
    <script src="./lib/vue_2.5.22.js"></script>
    <!-- 匯入 vue-router 檔案,為全域性 window 物件掛載 VueRouter 建構函式 -->
    <script src="./lib/vue-router_3.0.2.js"></script>

2.1.2 新增路由連結

    <!-- router-link 是 vue 中提供的標籤,預設會被渲染為 a 標籤 -->
    <!-- to 屬性預設會被渲染為 href 屬性 -->
    <!-- to 屬性的值預設會被渲染為 # 開頭的 hash 地址 --> <router-link to="/user">User</router-link>
    <router-link to="/register">Register</router-link>在這裡插入程式碼片

2.1.3 新增路由填充位

    <!-- 路由填充位(也叫做路由佔位符) -->
    <!-- 將來通過路由規則匹配到的元件,將會被渲染到 router-view 所在的位置 --> 
    <router-view></router-view>

2.1.4 定義路由元件

     var User = {
       template: '<div>User</div>'
     }
     var Register = {
       template: '<div>Register</div>'
     }

2.1.5 配置路由規則並建立路由例項

    // 建立路由例項物件 
    var router = new VueRouter({
    // routes 是路由規則陣列
    routes: [
      // 每個路由規則都是一個配置物件,其中至少包含 path 和 component 兩個屬性:
     // path 表示當前路由規則匹配的 hash 地址
     // component 表示當前路由規則對應要展示的元件
     {path:'/user',component: User},
     {path:'/register',component: Register}
   ]
 })

2.1.6 把路由掛載到 Vue 根例項中

    new Vue({
       el: '#app',
       // 為了能夠讓路由規則生效,必須把路由物件掛載到 vue 例項物件上
        router
    });

2.2 路由重定向

路由重定向指的是:使用者在訪問地址 A 的時候,強制使用者跳轉到地址 C ,從而展示特定的元件頁面;
通過路由規則的 redirect 屬性,指定一個新的路由地址,可以很方便地設定路由的重定向:

    var router = new VueRouter({
      routes: [
        // 其中,path 表示需要被重定向的原地址,redirect 表示將要被重定向到的新地址
        {path:'/', redirect: '/user'},
        {path:'/user',component: User},
        {path:'/register',component: Register}
      ]
   });

3. vue-router巢狀路由

3.1 巢狀路由用法

3.1.1 巢狀路由功能分析

  • 點選父級路由連結顯示模板內容。
  • 模板內容中又有子級路由連結。
  • 點選子級路由連結顯示子級模板內容。

在這裡插入圖片描述

3.1.2 父路由元件模板

  • 父級路由連結。
  • 父元件路由填充位。
     <p>
     <router-link to="/user">User</router-link>
     <router-link to="/register">Register</router-link>
     </p>
     <div>
     <!-- 控制組件的顯示位置 -->
     <router-view></router-view>
     </div>

3.1.3 子級路由模板

  • 子級路由連結
  • 子級路由填充位
     const Register = {
     template: `<div>
     <h1>Register 元件</h1>
     <hr/>
     <router-link to="/register/tab1">Tab1</router-link>
     <router-link to="/register/tab2">Tab2</router-link>
     <!-- 子路由填充位置 -->
     <router-view/>
     </div>`
 }

3.1.4 巢狀路由配置

父級路由通過children屬性配置子級路由。

 const router = new VueRouter({
     routes: [
       { path: '/user', component: User },
       {
         path: '/register',
         component: Register,
         // 通過 children 屬性,為 /register 新增子路由規則
         children: [
           { path: '/register/tab1', component: Tab1 },
           { path: '/register/tab2', component: Tab2 }
         ]
       }
     ]
 });

4. vue-router動態路由匹配

4.1 動態匹配路由的基本用法

思考:

<!– 有如下 3 個路由連結 --> <router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/user/3">User3</router-link>
// 定義如下三個對應的路由規則,是否可行???
{ path: '/user/1', component: User }
{ path: '/user/2', component: User }
{ path: '/user/3', component: User }

應用場景:通過動態路由引數的模式進行路由匹配

var router = new VueRouter({
 routes: [
 // 動態路徑引數 以冒號開頭
 { path: '/user/:id', component: User }
 ]
})
const User = {
 // 路由元件中通過$route.params獲取路由引數
 template: '<div>User {{ $route.params.id }}</div>'
}
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <!-- 匯入 vue 檔案 -->
    <script src="./lib/vue_2.5.22.js"></script>
    <script src="./lib/vue-router_3.0.2.js"></script>
  </head>
  <body>
    <!-- 被 vm 例項所控制的區域 -->
    <div id="app">
      <router-link to="/user/1">User1</router-link>
      <router-link to="/user/2">User2</router-link>
      <router-link to="/user/3">User3</router-link>
      <router-link to="/register">Register</router-link>

      <!-- 路由佔位符 -->
      <router-view></router-view>
    </div>

    <script>
      const User = {
        template: "<h1>User 元件 -- 使用者id為: {{$route.params.id}}</h1>",
      };

      const Register = {
        template: "<h1>Register 元件</h1>",
      };

      // 建立路由例項物件
      const router = new VueRouter({
        // 所有的路由規則
        routes: [
          { path: "/", redirect: "/user" },
          { path: "/user/:id", component: User },
          { path: "/register", component: Register },
        ],
      });

      // 建立 vm 例項物件
      const vm = new Vue({
        // 指定控制的區域
        el: "#app",
        data: {},
        // 掛載路由例項物件
        // router: router
        router,
      });
    </script>
  </body>
</html>

4.2 路由元件傳遞引數

$route與對應路由形成高度耦合,不夠靈活,所以可以使用props將元件和路由解耦。

4.2.1 props的值為布林型別

 const router = new VueRouter({
   routes: [
     // 如果 props 被設定為 true,route.params 將會被設定為元件屬性
     { path: '/user/:id', component: User, props: true }
   ]
 });
 
 const User = {
   props: ['id'], // 使用 props 接收路由引數
   template: '<div>使用者ID:{{ id }}</div>' // 使用路由引數
 };

4.2.2 props的值為物件型別

 const router = new VueRouter({
   routes: [
     // 如果 props 是一個物件,它會被按原樣設定為元件屬性
     { path: '/user/:id', component: User, props: { uname: 'lisi', age: 12 }}
   ]
 });
 
 const User = {
   props: ['uname', 'age'],
   template:<div>使用者資訊:{{ uname + '---' + age}}</div>'
 };

4.2.3 props的值為函式型別

 const router = new VueRouter({
   routes: [
     // 如果 props 是一個函式,則這個函式接收 route 物件為自己的形參
     { path: '/user/:id', 
         component: User, 
         props: route => ({ uname: 'zs', age: 20, id: route.params.id })}
     ]
 });
 
 const User = {
   props: ['uname', 'age', 'id'],
   template:<div>使用者資訊:{{ uname + '---' + age + '---' + id}}</div>'
 };

5. vue-router命名路由

5.1 命名路由的配置規則

為了更加方便的表示路由的路徑,可以給路由規則起一個別名,即為“命名路由”。

     const router = new VueRouter({
      routes: [
         {
           path: '/user/:id',
           name: 'user',
           component: User
         }
      ]
    });
 <router-link :to="{ name: 'user', params: { id: 123 }}">User</router-link>
 router.push({ name: 'user', params: { id: 123 }})

6. vue-router程式設計式導航

6.1 頁面導航的兩種方式

  • 宣告式導航:通過點選連結實現導航的方式,叫做宣告式導航。
    例如:普通網頁中的<a></a> 連結 或 vue 中的 <router-link></router-link>
  • 程式設計式導航:通過呼叫JavaScript形式的API實現導航的方式,叫做程式設計式導航。
    例如:普通網頁中的 location.href

常用的程式設計式導航 API 如下:

  • this.$router.push('hash地址')
  • this.$router.go(n)
 const User = {
   template: '<div><button @click="goRegister">跳轉到註冊頁面</button></div>',
   methods: {
     goRegister: function(){
       // 用程式設計的方式控制路由跳轉
       this.$router.push('/register');
     }
   }
 }
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <!-- 匯入 vue 檔案 -->
    <script src="./lib/vue_2.5.22.js"></script>
    <script src="./lib/vue-router_3.0.2.js"></script>
  </head>
  <body>
    <!-- 被 vm 例項所控制的區域 -->
    <div id="app">
      <router-link to="/user/1">User1</router-link>
      <router-link to="/user/2">User2</router-link>
      <router-link :to="{ name: 'user', params: {id: 3} }">User3</router-link>
      <router-link to="/register">Register</router-link>

      <!-- 路由佔位符 -->
      <router-view></router-view>
    </div>

    <script>
      const User = {
        props: ['id', 'uname', 'age'],
        template: `<div>
          <h1>User 元件 -- 使用者id為: {{id}} -- 姓名為:{{uname}} -- 年齡為:{{age}}</h1>
          <button @click="goRegister">跳轉到註冊頁面</button>
        </div>`,
        methods: {
          goRegister() {
            this.$router.push('/register')
          }
        },
      }

      const Register = {
        template: `<div>
          <h1>Register 元件</h1>
          <button @click="goBack">後退</button>
        </div>`,
        methods: {
          goBack() {
            this.$router.go(-1)
          }
        }
      }

      // 建立路由例項物件
      const router = new VueRouter({
        // 所有的路由規則
        routes: [
          { path: '/', redirect: '/user' },
          {
            // 命名路由
            name: 'user',
            path: '/user/:id',
            component: User,
            props: route => ({ uname: 'zs', age: 20, id: route.params.id })
          },
          { path: '/register', component: Register }
        ]
      })

      // 建立 vm 例項物件
      const vm = new Vue({
        // 指定控制的區域
        el: '#app',
        data: {},
        // 掛載路由例項物件
        // router: router
        router
      })
    </script>
  </body>
</html>

6.2 程式設計式導航引數規則

router.push() 方法的引數規則

 // 字串(路徑名稱)
 router.push('/home')
 // 物件
 router.push({ path: '/home' })
 // 命名的路由(傳遞引數)
 router.push({ name: '/user', params: { userId: 123 }})
 // 帶查詢引數,變成 /register?uname=lisi
 router.push({ path: '/register', query: { uname: 'lisi' }})