1-路由

1.1-路由的概念

  • 頁面訪問路徑和組件之間的對應關係

1.2-路由的安裝

npm i vue-router -S

1.3-路由的基本使用流程

1.3.1-第一步

  • 配置路由規則(數組)
import Home from './pages/Home'
import Login from './pages/Login'
const rotues=[
    {
        // 頁面訪問路徑
        path:'/home',
        // 頁面組件對象
        component:Home
    },
    {
        // 頁面訪問路徑
        path:'/login',
        // 頁面組件對象
        component:Login
    }
]

1.3.2-第二步

  • 根據路由規則數組, 創建路由實例對象
import Vue from 'vue';
// 1-導入路由模塊
import VueRouter from 'vue-router';
// 2-將路由模塊註冊成vue的插件
Vue.use(VueRouter);
// 3-創建路由實例對象
const  router=new VueRouter({
    // 路由規則數組
    routes:routes
});
// 4-導出路由對象

1.3.3-第三步

  • 將路由實例掛在到vue上
import router from './router/index';
new Vue({
    el:'#app',
    // 掛載路由實例
    router:router
});

1.3.4-第四步

  • 在根組件App.vue中添加路由佔位符合路由導航鏈接
<template>
  <!-- 必須有一個唯一的根標籤 -->
  <div id="app">
    <!-- 導航鏈接 -->
    <!-- to屬性: 指定頁面的跳轉地址, 必須和路由規則數組中的path屬性保持一致 -->
    <router-link to="/home">首頁</router-link>
    <router-link to="/reg">註冊</router-link>
    <router-link to="/login">登錄</router-link>
    <hr>
    <!-- 路由佔位符: 訪問地址匹配到的路由組件的顯示位置 -->
    <router-view></router-view>
   </div>
</template>

1.4-路由模式

  • hash模式:
  • 頁面訪問地址中帶有#, 默認路由模式
  • hash路由模式, 通過npm run build打包之後, 不需要web服務器的支持
new  VueRouter({
    // 路由規則數組
    routes,
    // mode可選值: hash, history
    mode:'hash'		
});
  • history模式:
  • 頁面訪問地址中不帶#
  • history路由模式, 通過npm run build打包之後,需要web服務器的支持
new  VueRouter({
    // 路由規則數組
    routes,
    // mode可選值: hash, history
    mode:'history'		
});

1.5-路由導航高亮

  1. 給默認的路由導航高亮類名router-link-active添加對應css屬性, 使其高亮顯示即可
  2. 自定義導航鏈接高亮類名
new  VueRouter({
    // 自定義導航鏈接高亮類名
    linkActiveClass:''
});

1.6-路由重定向

  • router/index.js
// 3-定義路由規則數組
const  routes=[
    {
        path:'/',
        // component:Home
        // 重定向
        redirect:'/login'
    }
]

1.7-命名路由

  • router/index.js
// 3-定義路由規則數組
const  routes=[
    {
        name:'index',
        path:'/',
        // component:Home
        // 重定向
        redirect:'/login'
    },
    {
        name:'home',
        path:'/home',
        component:Home
    },
    {
        name:'login',
        path:'/login',
        component:Login
    },
    {
        name:'reg',
        path:'/reg',
        component:Reg
    }
];
  • App.js
<router-link class="nav-btn" v-bind:to="{name:'home'}" tag="div">首頁</router-link>

1.8-編程式導航

  • 通過js的方式實現頁面跳轉
  • this.$router: 包含和頁面跳轉相關的方法
  • push(): 實現頁面跳轉, 追加一條訪問歷史
  • 路由字符串
this.$router.push('/home');
  • 路由對象
this.$router.push({name:'home'});
  • replace: 實現頁面跳轉, 覆蓋前一次的訪問歷史
  • 路由字符串
this.$router.replace('/home');
  • 路由對象
this.$router.replace({name:'home'});
  • go(): 實現頁面前進後者回退
  • 正數: 前進
  • 負數: 回退
  • forward(): 實現頁面前進一步
  • back(): 實現頁面回退一步

1.9-路由元信息

  • 定義

router/index.js

// 3-定義路由規則數組
const  routes=[
    {
        name:'index',
        path:'/',
        // component:Home
        // 重定向
        redirect:'/login'
    },
    {
        name:'home',
        path:'/home',
        component:Home,
        // 路由元信息
        meta:{
            title:'網站首頁'
        }
    },
    {
        name:'login',
        path:'/login',
        component:Login,
        meta:{
            title:'登錄頁面'
        }
    },
    {
        name:'reg',
        path:'/reg',
        component:Reg,
        meta:{
            title:'註冊頁面'
        }
    }
];
  • 調用
  • 使用路由元信息, 實現更新頁面標題
  • this.$route: 存儲的是和路由相關的屬性(包含路由元信息)

頁面組件中: 通過this.$route.meta讀取路由元信息

export default {
  created(){
    // this.$route: 存儲的是和路由相關的屬性(包含路由元信息)
    // 通過this.$route對象讀取路由元信息
    const title=this.$route.meta.title;
    // 通過操作真實dom, 實現更新頁面標題
    document.title=title;
  }
}

1.10-命名視圖

Vue 路由 基本操作 路由模式 hash路由模式的實現原理_字符串

  • 應用場景: 一個路由訪問地址, 對應多個視圖組件

1.10.1-配置命名視圖路由規則

router/index.js

import Home from '../pages/Home';
import Aside from '../components/Aside';
// 3-定義路由規則數組
const  routes=[
    // 一個訪問路徑, 對應多個組件, 需要用到命名視圖
    {
        name:'home',
        path:'/home',
        // component:Home,
        components:{
            // aside: 要和插入的router-view的name屬性保持一致
            // Aside: 組件對象
            aside:Aside,
            // content: 要和插入的router-view的name屬性保持一致
            // Home: 組件對象
            content:Home
        }
    }
}

1.10.2-在根組件中添加命名視圖

App.vue

<template>
  <!-- 必須有一個唯一的根標籤 -->
  <div id="app" class="container">
    <!-- 命名視圖aside -->
    <router-view name="aside"></router-view>
    <div class="right">
      <!-- 導航鏈接 -->
      <router-link class="nav-btn" v-bind:to="{name:'home'}" tag="div">首頁</router-link>
      <router-link class="nav-btn" :to="{name:'reg'}" tag="div">註冊</router-link>
      <router-link class="nav-btn" to="/login" tag="div">登錄</router-link>
      <router-link class="nav-btn" to="/ucenter" tag="div">我的</router-link>
      <hr />
      <!-- 命名視圖content -->
      <router-view name="content"></router-view>
      <!-- 默認視圖: 默認路由出口 -->
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {
  // 組件名字
  name: "App"
};
</script>

<style>
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}
#app {
  width: 1000px;
  margin: 20px auto;
}
h1 {
  margin-bottom: 10px;
}
/* 路由導航鏈接高亮顯示 */
.nav-btn {
  background: #ddd;
  border: 1px solid #eee;
  display: inline-block;
  width: 80px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  text-decoration: none;
}
/* 默認高亮類名:router-link-active */
/* 自定義導航鏈接高亮類名 */
.active {
  background: brown;
  color: #fff;
}

/* 命名視圖對應樣式 */
.container {
  display: flex;
  height: 600px;
}
.right {
  flex: 1;
  background: lightgreen;
}
</style>

1.11-動態路由

  • 定義動態路由規則
// 3-定義路由規則數組
const  routes=[
    // 動態路由, id動態路由參數
    {
        path:'/goods/:goodsId',
        component:Goods,
        // 路由元信息的定義
        meta:{
            title:'商品詳情',
            // 自定義屬性, auth:true,表示必須登錄之後, 才能訪問
            auth:false
        }
    }
];
  • 動態路由鏈接
<router-link class="nav-btn" to="/goods/100" tag="div">商品詳情</router-link>
  • 動態路由參數的獲取
this.$route.params

1.11.1-動態路由參數的解耦

  1. 在路由規則對象中添加如下配置
{
    path:'/goods/:goodsId',
    component:Home
    // 路由參數解耦
    props:true
}
  1. 在組件配置對象中添加如下配置
{
    data(){
      return {}  
    },
    props:['goodsId']
}
  1. 在組件視圖層直接通過goodsId獲取動態路由參數
<h1>{{goodsId}}</h1>
<!--完整寫法-->
<h1>{{$route.params.goodsId}}</h1>

1.12-通過查詢字符串的方式實現路由傳參

  1. 通過查詢字符串傳遞數據
<router-link class="nav-btn" to="/news?newsId=1&wd=vue" tag="div">新聞詳情</router-link>
  1. 組件內通過this.$route.query獲取查詢字符串對象
this.$route.query

1.13-路由懶加載

  • 作用: 提升頁面渲染性能
const Home=()=>import('../pages/Home');
const Login=()=>import('../pages/Login');
const Reg=()=>import('../pages/Reg');
const Ucenter=()=>import('../pages/Ucenter');
const Goods=()=>import('../pages/Goods');
const News=()=>import('../pages/News');

1.14-路由匹配模式

  • 默認是模糊匹配: 訪問地址中只要包含路由對象中的path, 就認為是匹配成功(所以會自動電量對應的導航鏈接)
啓用路由嚴格匹配模式
  • 在路由導航鏈接組件上添加exact屬性
<router-link exact tag="li" to="/">管理中心</router-link>

2-hash路由模式實現原理

  1. 監聽頁面錨點字符串的更新
<component :is="page"></component>
// 導入頁面組件
import Home from './pages/Home';
import Reg from './pages/Reg';
import Login from './pages/Login';
export default {
  // 組件名字
  name: "App",
  data(){
    return {
      page:'Home'
    }
  },
  // 註冊子組件
  components: {Home,Reg,Login},
  created(){
    window.addEventListener('hashchange',()=>{
      // console.log('hashchange',location.hash.split('/')[1]);
      // 更新page變量的值
      this.page=location.hash.split('/')[1];
    });
  }
};
  1. 根據錨點字符串, 顯示對應的組件

3-案例

3.1-後台管理系統

  • 根組件

App.vue

<template>
  <div class="container">
    <div class="left">
      <ul class="navbar">
        <!-- <li :class="page==='Main'?'active':''" @click="changePage('Main')">管理中心</li>
        <li :class="page==='Goods'?'active':''" @click="changePage('Goods')">商品管理</li>
        <li :class="page==='User'?'active':''" @click="changePage('User')">會員管理</li>
        <li :class="page==='Order'?'active':''" @click="changePage('Order')">訂單管理</li> -->
        <!-- 啓用路由嚴格匹配模式 -->
        <router-link exact tag="li" to="/">管理中心</router-link> 
        <router-link tag="li" to="/goods">商品管理</router-link> 
        <router-link tag="li" to="/user">會員管理</router-link> 
        <router-link tag="li" to="/order">訂單管理</router-link> 

      </ul>
    </div>
    <div class="right">
      <!-- 頭部 -->
      <Header></Header>
      <div class="content">
        <!-- <component :is="page"></component> -->
        <!-- 路由佔位符 -->
        <router-view></router-view>
      </div>
      <!-- 底部 -->
      <Footer />
    </div>
  </div>
</template>

<script>
// 1-導入頁組件
// import Main from "./pages/Main";
// import Goods from "./pages/Goods";
// import Order from "./pages/Order";
// import User from "./pages/User";
// 導入功能組件
import Header from "./components/Header";
import Footer from "./components/Footer";

export default {
  // 2-註冊組件
  components: {
    // Main,
    // Goods,
    // Order,
    // User,
    Header,
    Footer
  },
  data() {
    return {
      // 頁面組件名稱
      page: "Order"
    };
  },
  methods: {
    // 切換頁面
    changePage(page) {
      this.page = page;
    }
  }
};
</script>

<style>
*{
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}
.container {
  background-color: #ddd;
  /* vh:相對單位; 100vh=屏幕的高度  1vh==1/100屏幕高度; viewport height */
  height: 100vh;
  display: flex;
}
/* 左側導航欄 */
.container .left {
  width: 226px;
  background: #00152a;
}
.left .navbar li {
  list-style: none;
  line-height: 50px;
  color: #fff;
  text-align: center;
  cursor: pointer;
}
.left .navbar li:hover {
  background: #0077b8;
}
.left .navbar li.active {
  background: #0077b8;
}

.container .right {
  flex: 1;
  display: flex;
  flex-direction: column;
}
.right .header {
  height: 60px;
  line-height: 60px;
  text-align: center;
  background: #fff;
}
.right .content {
  margin: 10px;
  background: #fff;
  height: 300px;
  text-align: center;
  flex: 1;
}
.right .footer {
  line-height: 60px;
  text-align: center;
  background: #fff;
}
</style>
  • 路由文件

ruoter/index.js

// 1-導入路由模塊
import Vue from 'vue'
import VueRouter from 'vue-router';

// 2-註冊插件
Vue.use(VueRouter);


// 3-創建路由規則
// 導入頁面組件
import Main from '../pages/Main';
import Goods from '../pages/Goods';
import Order from '../pages/Order';
import User from '../pages/User';

const routes=[
    {
        // 模糊匹配: 訪問地址中包含路由規則對象中的path, 那麼認為匹配成功
        path:'/',
        component:Main,
        meta:{
            title:'管理中心'
        }
    },
    {
        path:'/goods',
        component:Goods,
        meta:{
            title:'商品管理'
        }
    },
    {
        path:'/user',
        component:User,
        meta:{
            title:'會員管理'
        }
    },
    {
        path:'/order',
        component:Order,
        meta:{
            title:'訂單中心'
        }
    }
];

// 4-創建路由對象
const router=new  VueRouter({
    routes,
    mode:'hash',
    linkActiveClass:'active'
});

// 5-導出路由實例對象
export default router;
  • 項目入口文件

/main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
// 導入了根組件
import App from './App'
// 導入路由實例對象
import router from './router'
/* eslint-disable no-new */
new Vue({
  // 模板編譯之後掛載的容器
  el: '#app',
  // 掛載路由模塊
  router,
  components: { App },
  // vue實例的視圖模板: 使用根組件App充當默認視圖
  template:'<App/>'
})

4-在線參考文檔

  • vue-router在線文檔