多個路由通過路由器進行管理。 前端路由的概念和原理 (編程中的)路由(router)就是一組key-value對應關係,分為:後端路由和前端路由 後端路由指的是:請求方式、請求地址和function處理函數之間的對應關係 在SPA程式中,所有組件的展示和切換都在這唯一的一個頁面內完成,此時,不同組件 ...
多個路由通過路由器進行管理。
前端路由的概念和原理
(編程中的)路由(router)就是一組key-value
對應關係,分為:後端路由和前端路由
後端路由指的是:請求方式、請求地址和function處理函數之間的對應關係
在SPA程式中,所有組件的展示和切換都在這唯一的一個頁面內完成,此時,不同組件之間的切換需要通過前端路由來實現
通俗易懂的來說,前端路由是:Hash地址(url中#的部分)與組件之間的對應關係
前端路由的工作方式
- 用戶點擊了頁面上的路由鏈接
- 導致了URL地址欄中的Hash值發生了變化
- 前端路由監聽到了Hash地址的變化
- 前端路由把當前Hash地址對應的組件渲染到瀏覽器中
實現簡易的前端路由(底層實現原理)
App.vue根組件
<template>
<div>
<h1>這是App根組件</h1>
<a href="#/Home">Home</a>
<a href="#/Movie">Movie</a>
<a href="#/About">About</a>
<hr>
<component :is="comName"></component>
</div>
</template>
<script>
import MyHome from './MyHome.vue'
import Mymovie from './MyMovie.vue'
import MyAbout from './MyAbout.vue'
import { walkFunctionParams } from '@vue/compiler-core'
export default {
name:'App',
components:{
MyHome,
MyAbout,
Mymovie,
},
data(){
return{
comName:'MyHome'
}
},
created(){
window.onhashchange=()=>{
switch(location.hash){
case '#/Home':
this.comName='MyHome'
break
case '#/Movie':
this.comName='MyMovie'
break
case '#/About':
this.comName='MyAbout'
break
}
}
}
}
</script>
<style lang="less" scoped>
</style>
vue-router的基本使用
vue-router是vue.js官方給出的路由解決方案,它只能結合vue項目進行使用,能夠輕鬆的管理SPA項目中的組件切換。
- vue-router 3.x 只能結合vue2進行使用,官方文檔:https://router.vuejs.org/zh/
- vue-router 4.x 只能結合vue3進行使用,官方文檔:https://next.router.vuejs.org/
二者差異主要是在聲明router配置文件上。
vue-router 3.x的基本使用步驟
- 在項目中安裝vue-router
npm install [email protected] -S
- 在
src
源代碼目錄下,新建router/index.js
路由模塊
//導入包
import Vue from 'vue'
import VueRouter from 'vue-router'
//插件引入
Vue.use(VueRouter)
//創建路由的實例對象
const router = new VueRouter
//向外共用
export default router
- 在入口文件
main.js
中引入
import router from '@/router/index.js'
......
new Vue({
...
router:router
...
}).$mount('#app')
vue-router 4.x的基本使用步驟
- 在項目中安裝vue-router
npm install vue-router@next -S
- 定義路由組件
MyHome.vue、MyMovie.vue、MyAbout.vue
- 聲明路由鏈接和占位符
可以使用<router-link>
標簽(會被渲染成a鏈接)來聲明路由鏈接,並使用<router-view>
標簽來聲明路由占位符
<template>
<div>
<h1>這是App根組件</h1>
<!-- <a href="#/Home">Home</a>
<a href="#/Movie">Movie</a>
<a href="#/About">About</a> -->
<!-- 聲明路由鏈接 -->
<router-link to="/home">首頁</router-link>
<router-link to="/movie">電影</router-link>
<router-link to="/about">我的</router-link>
<hr>
<!-- 路由占位符 -->
<router-view></router-view>
<component :is="comName"></component>
</div>
</template>
- 創建路由模塊
從項目中創建router.js路由模塊,按照以下四步:
從vue-router中按需導入兩個方法
import { createRouter, createWebHashHistory } from 'vue-router' //createRouter方法用於創建路由的實例對象 //createWebHashHistory用於指定路由的工作方式(hash模式)
導入需要使用路由控制的組件
import MyHome from './MyHome.vue' import MyMovie from './MyMovie.vue' import MyAbout from './MyAbout.vue'
創建路由實例對象
const router = createRouter({ history: createWebHashHistory(), routes: [ { path: '/home', component: MyHome }, { path: '/movie', component: MyMovie }, { path: '/about', component: MyAbout }, ] })
向外共用路由實例對象
export default router
在main.js中導入並掛載路由模塊
import { createApp } from 'vue' import App from './App.vue' import './index.css' import router from './components/router' const app = createApp(App) //掛載路由寫法 app.use(router) app.mount('#app')
- 導入並掛載路由模塊
vue-router的高級用法
路由重定向
指的是:用戶在訪問地址A的時候,強制用戶跳轉到地址C,從而展示特點的組件頁面
通過路由規則的redirect屬性,指定新的路由地址
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/home', component: MyHome
},
{
path: '/',redirect:'/home' //訪問根路徑會重定向到home組件
},
{
path: '/movie', component: MyMovie
},
{
path: '/about', component: MyAbout
},
]
})
路由傳參
query
參數
<router-link :to="/about/home/message?id=123&title='abc'">我的</router-link>
<router-link :to="{
path:'/about/home/message',
query:{
id:123,
title:'abc'
}
}">
我的
</router-link>
params
參數
聲明時:
path:'/about/home/message/:id/:title'
<router-link :to="/about/home/message/123/abc">我的</router-link>
<router-link :to="{
name:'my',
params:{
id:123,
title:'abc'
}
}">
我的
</router-link>
this.$route 是路由的"參數對象"
this.$router 是路由的"導航對象"
路由高亮
- 使用預設的高亮class類名
被激活的路由鏈接,預設會使用router-link-active的類名,開發者可以使用此類名選擇器,為激活的路由鏈接設置高亮樣式
- 自定義路由高亮的class類
在創建路由的實例對象時,開發者可以基於linkActiveClass屬性,自定義類名
const router = createRouter({
history: createWebHashHistory(),
linkActiveClass:'active-router',
routes: [
{
path: '/home', component: MyHome
},
{
path: '/',redirect:'/home' //訪問根路徑會重定向到home組件
},
{
path: '/movie', component: MyMovie
},
{
path: '/about', component: MyAbout
},
]
})
嵌套路由
通過路由來實現組件的嵌套展示
步驟:
- 聲明子路由鏈接和子路由占位符
<template>
<div>MyAbout組件</div>
<hr>
<router-link to="/about/tab1">tab1</router-link>
<router-link to="/about/tab2">tab2</router-link>
<router-view></router-view>
</template>
- 在父路由規則中,通過children屬性嵌套聲明子路由規則
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/home', component: MyHome
},
{
path: '/movie', component: MyMovie
},
{
path: '/about', component: MyAbout,children:[
{
path:'tab1',component:Tab1
},
{
path:'tab2',component:Tab2
},
]
},
]
})
子路由規則的path不要以/開頭
在嵌套路由中實現路由的重定向
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/home', component: MyHome
},
{
path: '/movie', component: MyMovie
},
{
path: '/about',
component: MyAbout,
redirect:'/about/tab1',
children:[
{
path:'tab1',component:Tab1
},
{
path:'tab2',component:Tab2
},
]
},
]
})
動態路由匹配
指的是:把Hash地址中可變的部分定義為參數項,從而提高路由規則的復用性,在vue-router中使用英文冒號:來定義路由的參數
{
path: '/movie/:id', component: MyMovie
},
獲取動態路由參數值的方法:
- $route.params參數對象
<template>
<div>Mymovie組件---{{$route.params.id}}</div>
</template>
- 使用props接受路由參數
{
path: '/movie/:id', component: MyMovie,
props: true,
},
為了簡化路由參數的獲取形式,vue-router允許在路由規則中開啟props傳參
編程式導航
通過調用API實現導航的方式,叫做編程式導航,與之對應的,通過點擊鏈接實現導航的方式,叫做聲明式導航。
- 普通網頁中點擊a鏈接,vue項目中點擊
<router-link>
都屬於聲明式導航 - 平臺網頁中調用
location.herf
跳轉到新頁面的方式,屬於編程式導航
vue-router中編程式導航API
- this.$router.push('hash地址') 跳轉到指定Hash地址,並增加一條歷史記錄,從而展示對應的組件。
- this.$router.replace('hash地址') 跳轉到指定Hash地址,並替換當前的歷史記錄,從而展示對應的組件。
- this.$router.go('數值n') 實現導航歷史的前進、後退(-1),超過最大層數,則原地不動。
$router.back() 後退到上一層頁面
$router.forward() 前進到下一層頁面
命名路由
通過name屬性為路由規則定義名稱,叫做命名路由,name值不能重覆,具有唯一性
Hash地址特別長時體現出命名路由的優勢
- 使用命名路由實現聲明式導航
<template>
<h3>
MyHome組件
</h3>
<router-link :to="{name:'mov',params:{id : 3}}">goToMovie</router-link>
</template>
<script>
export default {
name:'MyHome',
}
</script>
- 使用命名路由實現編程式導航
<template>
<h3>
MyHome組件
</h3>
<button @click="goToMovie(3)">
goToMovie
</button>
</template>
<script>
export default {
method: {
goToMovie(id) {
this.$router.push({name:'mov',params:{id : 3}})
}
}
}
</script>
導航守衛
導航守衛可以控制路由的訪問許可權
如何聲明全局的導航守衛
全局的導航守衛會攔截每個路由規則,從而對每個路由都進行訪問許可權的控制
const router = createRouter({
...
})
//調用路由實例對象的beforeEach函數,fn必須是一個函數嗎,每次攔截後,都會調用fn進行處理
//聲明全局的導航守衛,fn稱為守衛方法
router.beforeEach(fn)
router.beforeEach(()=>{
console.log('Ok')
})
守衛方法的三個形參(可選)
router.beforeEach((to,from,mext)=>{
console.log('Ok')
//to 目標路由對象(信息)
//from當前導航正要離開的路由對象
//next 是一個函數,表示放行
})
註:
在守衛方法中不聲明next形參,則預設允許用戶訪問每一個路由
在守衛方法中聲明瞭next形參,則必須調用next()函數,否則不允許用戶訪問如何一個路由!
next函數的3種調用方式
//聲明全局的導航守衛
router.beforeEach((to, from, next) => {
if (to.path === '/main') {
//證明用戶要訪問後臺主頁
next(false)//強制用戶停留在之前所處的組件
next('login')//強制用戶調轉到指定頁面
} else {
//證明用戶要訪問的不是後臺主頁
next()
}
})
結合token控制後臺主頁的訪問許可權
router.beforeEach((to, from, next) => {
const tokenStr = localStorage.getItem('token') //讀取token
if (to.path === '/main' && !tokenStr) { //token不存在,需要登錄
//證明用戶要訪問後臺主頁
// next(false)//強制用戶停留在之前所處的組件
next('login')//強制用戶調轉到指定頁面
} else {
//證明用戶要訪問的不是後臺主頁
next()
}
})
Hash&History
路由器的兩種工作模式:hash
&history
。
對於url
來說:#及後面的內容就是hash
值,hash
值不會帶給伺服器。
hash
模式:
- 地址中永遠帶著
#
號,不美觀; - 若地址校驗嚴格,會被標記為不合法;
- 相容性較好;
history
模式:
- 地址乾凈,美觀;
- 相容性比
hash
模式較差; - 應用部署上線需要後端支持,解決刷新頁面服務端404問題;(
node
可以使用connect-history-api-fallback
)