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-路由導航高亮
- 給默認的路由導航高亮類名
router-link-active添加對應css屬性, 使其高亮顯示即可 - 自定義導航鏈接高亮類名
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-命名視圖
- 應用場景: 一個路由訪問地址, 對應多個視圖組件
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-動態路由參數的解耦
- 在路由規則對象中添加如下配置
{
path:'/goods/:goodsId',
component:Home
// 路由參數解耦
props:true
}
- 在組件配置對象中添加如下配置
{
data(){
return {}
},
props:['goodsId']
}
- 在組件視圖層直接通過
goodsId獲取動態路由參數
<h1>{{goodsId}}</h1>
<!--完整寫法-->
<h1>{{$route.params.goodsId}}</h1>
1.12-通過查詢字符串的方式實現路由傳參
- 通過查詢字符串傳遞數據
<router-link class="nav-btn" to="/news?newsId=1&wd=vue" tag="div">新聞詳情</router-link>
- 組件內通過
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路由模式實現原理
- 監聽頁面錨點字符串的更新
<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];
});
}
};
- 根據錨點字符串, 顯示對應的組件
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在線文檔