5.路由
5.1 Vue路由
5.1.1 Vue路由基礎
Vue路由例項:
<body>
<div id="app">
<p>
<!-- 這裡使用router-link標籤來實現路由跳轉 -->
<router-link to="/home">首頁</router-link><br>
<router-link to="/about">關於</router-link>
</p>
<!-- 路由出口(這裡顯示路由的內容) -->
<router-view></router-view>
</div>
<script src="../js/vue3.js"></script>
<script src="../js/vue-router.js"></script>
<script>
// 1、定義路由元件
const Home = {
template: '<div>首頁</div>'
}
const About = {
template: '<div>關於</div>'
}
// 2、定義路由規則(每一個路徑對映一個路由元件)
const routes = [
{
path: '/home',
component: Home
}, {
path: '/about',
component: About
}
]
// 3、建立Vue路由例項
const router = VueRouter.createRouter({
// 配置路由模式
history: VueRouter.createWebHashHistory(),
// 配置路由規則(如果路由規則名為routes,那麼可以簡寫為:routes)
routes: routes
})
// 4、將路由物件掛載到Vue例項上
Vue.createApp({
}).use(router).mount('#app')
</script>
</body>
5.1.2 巢狀路由
<body>
<div id="app">
<div>
<p>
<router-link to="/home">首頁</router-link><br>
<router-link to="/about">關於</router-link>
</p>
<router-view></router-view>
</div>
</div>
<script src="../js/vue3.js"></script>
<script src="../js/vue-router.js"></script>
<script>
const Home = {
template: `<div>
<p>首頁</p>
<router-link to="/home/login">登入</router-link><br>
<router-link to="/home/register">註冊</router-link>
<router-view></router-view>
</div>`
}
const About = {
template: '<div>關於</div>'
}
const Login = {
template: '<div>登入</div>'
}
const Register = {
template: '<div>註冊</div>'
}
const routes = [
{
path: '/',
redirect: '/home'
}, {
path: '/home',
component: Home,
children: [
{
path: '/home',
redirect: '/home/login'
}, {
path: '/home/login',
component: Login
}, {
path : '/home/register',
component: Register
}
]
}, {
path: '/about',
component: About
}
]
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes
})
Vue.createApp({
}).use(router).mount('#app')
</script>
</body>
5.1.3 路由傳參
5.1.3.1 params形式傳參
params
形式傳參是 Vue Router 中一種透過 URL 傳遞引數的方式。具體來說,它允許你在路由路徑中定義引數,並在導航時透過這些引數傳遞資料。這種方式通常用於動態路由,其中路由路徑的一部分是可變的。
<body>
<div id="app">
<p>
<router-link to="/home">首頁</router-link><br>
<router-link :to="{ name: 'About', params: { id: userID, name: userName } }">關於</router-link>
</p>
<router-view></router-view>
</div>
<script src="../js/vue3.js"></script>
<script src="../js/vue-router.js"></script>
<script>
const Home = {
template: '<div>首頁</div>'
}
const About = {
template: `<div>
關於<br>
引數1:{{ $route.params.id }}<br>
引數2:{{ $route.params.name }}
</div>`,
props: ['id', 'name']
}
const routes = [
{
path: '/',
redirect: Home
}, {
path: '/home',
name: 'Home',
component: Home,
props: true
}, {
path: '/about/:id/:name', // 明確定義引數 id 和 name
name: 'About',
component: About,
props: true
}
]
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes
})
Vue.createApp({
data() {
return {
userID: 123,
userName: '張三'
}
}
}).use(router).mount('#app')
</script>
</body>
5.1.3.2 query形式傳參
query
形式傳參是 Vue Router 中另一種透過 URL 傳遞引數的方式。與 params
形式不同,query
引數是透過 URL 的查詢字串(query string)傳遞的,通常顯示在 URL 的問號後面,例如 http://example.com/about?id=123&name=張三
。
<body>
<div id="app">
<p>
<router-link to="/home">首頁</router-link><br>
<router-link :to="{ path: '/about', query: {id: userID, name: userName} }">關於</router-link>
</p>
<router-view></router-view>
</div>
<script src="../js/vue3.js"></script>
<script src="../js/vue-router.js"></script>
<script>
const Home = {
template: `<div>首頁</div>`
}
const About = {
template: `<div>
關於<br>
引數1:{{ $route.query.id }}<br>
引數2:{{ $route.query.name }}
</div>`
}
const routes = [
{
path: '/',
redirect: '/home',
},
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
}
]
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes
})
Vue.createApp({
data() {
return {
userName: '張三',
userID: 123
}
}
}).use(router).mount('#app')
</script>
</body>
5.1.3.3 params方式與query的區別
params
和 query
是 Vue Router 中兩種不同的傳參方式,它們在用法和表現上有一些顯著的區別:
- URL 結構
- params 傳參:
- 引數直接嵌入在路徑中,例如
/about/123/張三
。 - URL 結構為
/about/:id/:name
。 - 引數是路徑的一部分,不可省略。
- 引數直接嵌入在路徑中,例如
- query 傳參:
- 引數透過查詢字串傳遞,例如
/about?id=123&name=張三
。 - URL 結構為
/about
,引數附加在 URL 後面,用問號?
分隔。 - 引數是可選的,可以省略。
- 引數透過查詢字串傳遞,例如
- 定義方式
- params 傳參:
- 在路由配置中定義路徑引數,例如
path: '/about/:id/:name'
。 - 在導航時透過
params
屬性傳遞引數,例如:to="{ name: 'About', params: { id: userID, name: userName } }"
。
- 在路由配置中定義路徑引數,例如
- query 傳參:
- 在路由配置中不需要定義引數。
- 在導航時透過
query
屬性傳遞引數,例如:to="{ name: 'About', query: { id: userID, name: userName } }"
。
- 訪問方式
- params 傳參:
- 在元件中透過
$route.params
訪問引數,例如{{ $route.params.id }}
。
- 在元件中透過
- query 傳參:
- 在元件中透過
$route.query
訪問引數,例如{{ $route.query.id }}
。
- 在元件中透過
- 引數的可見性和可變性
- params 傳參:
- 引數直接顯示在 URL 中,使用者可以直接看到和修改。
- 引數是路徑的一部分,不可省略,且必須與路徑定義匹配。
- query 傳參:
- 引數顯示在 URL 的查詢字串中,使用者也可以看到和修改。
- 引數是可選的,可以省略,且不需要與路徑定義匹配。
- 適用場景
- params 傳參:
- 適用於需要將引數作為路徑一部分的場景,例如動態路由、資源標識等。
- 引數是路徑的一部分,不可省略,適用於必須傳遞引數的場景。
- query 傳參:
- 適用於可選引數、過濾條件、排序等場景。
- 引數是可選的,可以省略,適用於引數不是必須的場景。
5.1.3.4 restful風格傳參
如果我們即想使用params方式傳參,又不想在重新整理是丟失引數,那麼我們可以使用restful風格傳參。
<body>
<div id="app">
<p>
<router-link to="/home">首頁</router-link><br>
<router-link to="/about/123/'張三'">關於</router-link>
</p>
<router-view></router-view>
</div>
<script src="../js/vue3.js"></script>
<script src="../js/vue-router.js"></script>
<script>
const Home = {
template: '<div>首頁</div>'
}
const About = {
template: `<div>
關於<br>
ID: {{ $route.params.id }}<br>
姓名: {{ $route.params.name }}
</div>`
}
const routes = [
{
path: '/',
redirect: '/home'
}, {
path: '/home',
name: Home,
component: Home
}, {
path: '/about/:id/:name',
name: About,
component: About
}
]
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes
})
Vue.createApp({
}).use(router).mount('#app')
</script>
</body>
5.2 程式設計式路由
程式設計式路由是指在Web應用中透過編寫程式碼來實現頁面之間的導航,而不是透過使用者點選連結(如<a>
標籤)來實現。這種方式允許開發者根據應用的邏輯和狀態來控制導航行為,從而實現更復雜和動態的使用者體驗。
程式設計式路由的主要用途:
- 條件導航:根據應用的狀態或使用者的操作來決定導航到哪個頁面。
- 動態引數傳遞:在導航時傳遞動態引數,如使用者ID、查詢引數等。
- 前進和後退:實現頁面的前進和後退功能,類似於瀏覽器的前進和後退按鈕。
- 重定向:根據某些條件自動重定向使用者到不同的頁面。
5.2.1 利用JS實現路由轉跳
<body>
<div id="app">
<button @click="toHome">首頁</button>
<button @click="toAbout">關於</button>
<button @click="toLogin">登入</button><br>
<button @click="toForward">前進</button>
<button @click="toBack">後退</button>
<router-view></router-view>
</div>
<script src="../js/vue3.js"></script>
<script src="../js/vue-router.js"></script>
<script>
const Home = {
template: '<div>首頁</div>'
}
const About = {
template: `<div>
關於<br>
ID: {{ $route.query.id }}<br>
name: {{ $route.query.name }}
</div>`
}
const Login = {
template: '<div>登入</div>'
}
const routes = [
{
path:'/',
redirect:'/home'
}, {
path:'/home',
component: Home
}, {
path:'/about',
component: About
}, {
path:'/login',
component: Login
}
]
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes
})
Vue.createApp({
data() {
return {
userID: 123,
userName: '張三'
}
},
methods: {
toHome() {
this.$router.push('/home')
},
toAbout() {
this.$router.push({path:'/about', query: {id: this.userID, name: this.userName}})
},
toLogin() {
this.$router.push('/login')
},
toForward() {
// this.$router.forward()
this.$router.go(1)
},
toBack() {
// this.$router.back()
this.$router.go(-1)
}
}
}).use(router).mount('#app')
</script>
</body>
5.2.2 透過watch實現路由監聽
透過watch屬性設定監聽$route變化,達到監聽路由跳轉的目的。
<body>
<div id="app">
<router-link to="/home">首頁</router-link><br>
<router-link to="/about">關於</router-link>
<router-view></router-view>
</div>
<script src="../js/vue3.js"></script>
<script src="../js/vue-router.js"></script>
<script>
const Home = { template: '<div>首頁</div>' }
const About = { template: '<div>關於</div>' }
const routes = [
{ path: '/', redirect: '/home' },
{ path: '/home', component: Home },
{ path: '/about', component: About }
]
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes
})
Vue.createApp({
// 路由監聽
watch: {
$route(newRoute, oldRoute) {
console.log(newRoute, oldRoute)
}
}
}).use(router).mount('#app')
</script>
</body>
5.2.3 導航守衛
路由守衛(Route Guards)是用於控制路由訪問許可權的一種機制,它們可以在導航到某個路由之前、之後或過程中執行一些邏輯,比如驗證使用者許可權、載入資料等。
以下是一些常見的路由守衛型別:
- beforeEach: 全域性前置守衛。
- beforeResolve: 全域性解析守衛。
- afterEach: 全域性後置鉤子。
- beforeEnter: 路由獨享的守衛。
- beforeRouteEnter: 元件內的守衛。
- beforeRouteUpdate: 元件內的守衛。
- beforeRouteLeave: 元件內的守衛。
<body>
<div id="app">
<p>
<!-- 這裡使用router-link標籤來實現路由跳轉 -->
<router-link to="/home">首頁</router-link><br>
<router-link to="/about">關於</router-link><br>
<router-link to="/login">登入</router-link>
</p>
<!-- 路由出口(這裡顯示路由的內容) -->
<router-view></router-view>
</div>
<script src="../js/vue3.js"></script>
<script src="../js/vue-router.js"></script>
<script>
const Home = {
template: '<div>首頁</div>'
}
const About = {
template: '<div>關於</div>'
}
const Login = {
template: '<div>登入</div>'
}
const routes = [
{
path: '/',
redirect: '/login'
}, {
path: '/home',
component: Home
}, {
path: '/about',
component: About
}, {
path: '/login',
component: Login
}
]
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes: routes
})
// 路由守衛
router.beforeEach((to, from, next)=>{
// 建立守衛規則
const nextRoute = ['/home', '/about']
// 使用isLogin來模擬是否登入
let isLogin = true
// 判斷topath是否需要驗證,如果當前路由是登入頁面,並且未登入,則跳轉到登入頁面
// indexOf()是用來判斷陣列中是否存在某個元素的,如果存在,則返回元素的索引值,否則返回-1
if(nextRoute.indexOf(to.path) >= 0) {
if(!isLogin) {
router.path('/login')
}
}
// 驗證透過後繼續往下執行
next()
})
Vue.createApp({}).use(router).mount('#app')
</script>
</body>