本小節我們介紹如何嵌套使用 VueRouter。嵌套路由在日常的開發中非常常見,如何定義和使用嵌套路由是本節的重點。同學們在學完本節課程之后需要自己多嘗試配置路由。
實際項目中的應用界面,通常由多層嵌套的組件組合而成。同樣地,URL 中各段動態路徑也按某種結構對應嵌套的各層組件,例如:
/article/vue /article/react
+------------------+ +-----------------+
| Article | | Article |
| +--------------+ | | +-------------+ |
| | Vue | | +------------> | | React | |
| | | | | | | |
| +--------------+ | | +-------------+ |
+------------------+ +-----------------+
代碼塊12345678
借助 vue-router,使用嵌套路由配置,就可以很簡單地表達這種關系。 在上一小節中我們學習了如何配置一個路由信息:
{
path: '路由地址',
component: '渲染組件'
}
要配置嵌套路由,我們需要在配置的參數中使用 children 屬性:
{
path: '路由地址',
component: '渲染組件',
children: [
{
path: '路由地址',
component: '渲染組件'
}
]
}
接下來我們對上一小節的例子來做一個改造:在文章頁面,我們對文章進行分類,提供兩個鏈接按鈕 vue、react,點擊可以跳轉到對應的文章列表,具體代碼示例如下:
實例演示
<!DOCTYPE html>
<html lang="en">
<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>
</head>
<body>
<div id="app">
<div>
<router-link to="/index">首頁</router-link>
<router-link to="/article">文章</router-link>
</div>
<router-view></router-view>
</div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script type="text/javascript">
const Index = Vue.component('index', {
template: '<div>Hello,歡迎使用慕課網學習 Vue 教程!</div>',
})
const Article = Vue.component('myArticle', {
template: `<div>
<div>
<router-link to="/article/vue">vue</router-link>
<router-link to="/article/react">react</router-link>
</div>
<router-view></router-view>
</div>`,
})
const VueArticle = Vue.component('vueArticle', {
template: `<ul><li>1. Vue 基礎學習</li><li>2. Vue 項目實戰</li></ul>`,
})
const ReactArticle = Vue.component('reactArticle', {
template: `<ul><li>1. React 基礎學習</li><li>2. React 項目實戰</li></ul>`,
})
const routes = [
{ path: '/index', component: Index },
{
path: '/article',
component: Article ,
children: [
{
path: 'vue',
component: VueArticle ,
},
{
path: 'react',
component: ReactArticle ,
}
]
}
]
const router = new VueRouter({
routes: routes
})
var vm = new Vue({
el: '#app',
router,
data() {
return {}
}
})
</script>
</html>
"運行案例" 可查看在線運行效果
代碼解釋: HTML 代碼第 12-13 行,我們定義了兩個跳轉鏈接。 HTML 代碼第 15 行,我們使用 <router-view></router-view> 組件來渲染匹配組件。 JS 代碼第 5-7 行,我們定義了組件 Index。 JS 代碼第 9-17 行,我們定義了組件 Article,組件內部使用 <router-link></router-link> 定義出來兩個跳轉鏈接,使用 <router-view></router-view> 來渲染匹配組件。 JS 代碼第 19-21 行,我們定義了組件 VueArticle. JS 代碼第 23-25 行,我們定義了組件 ReactArticle。 JS 代碼第 27-43 行,我們定義了路由數組,在 ‘/article’ 中配置來嵌套路由 children JS 代碼第 44-46 行,創建 router 實例,然后傳 routes 配置。 JS 代碼第 49 行,通過 router 配置參數注入路由。
在上述的例子中,我們通過 ‘/article/vue’ 來訪問嵌套路由,但是有時候你可能不希望使用嵌套路徑,這時候我們可以對上面例子中的配置信息做一點修改:
const routes = [
{ path: '/index', component: Index },
{
path: '/article',
component: Article ,
children: [
{
path: '/vueArticle',
component: VueArticle ,
},
{
path: '/reactArticle',
component: ReactArticle ,
}
]
}
]
以 ‘/’ 開頭的嵌套路徑會被當作根路徑,因此,我們訪問 ‘/vueArticle’ 就相當于訪問之前的 ‘/article/vue’。
本節,我們帶大家學習了 VueRouter 嵌套路由的使用方法,主要知識點有以下幾點:
ue3 嵌套路由的使用和 Vue2 相差不大,主要的區別是 Vue3 的路由實例化使用了 createApp() 方法,所以實例化路由時需要傳入根組件。另外,Vue3 的路由對象除了包含 Vue2 中的導航守衛、導航鉤子和解析守衛等功能外,還新增了 meta prop 和 route prop。
在使用嵌套路由時,建議將路由按照功能模塊進行分層,每一層代表一個主要的功能塊,每個層級下的路由數量不要過多,一般建議不要超過 10 個,層級也不要超過 5 層。同時,根據實際業務需求,可以適當調整路由層級和數量,以達到更好的管理和使用效果。
import {
createRouter,
createWebHashHistory,
RouteRecordRaw
} from "vue-router";
// createWebHashHistory,createWebHistory
const routes: RouteRecordRaw[] = [
{
path: '/',
redirect: '/home',
},
{
path: '/home',
name: 'Home',
component: () => import('@/views/Home/index.vue'),
meta: {
title: 'Home Page',
roles: ['admin', 'admin1']
},
children: [
{
path: 'lx',
name: 'Lx',
component: () => import('@/views/Home/Lx.vue'),
// 也可以使用props傳參方式接收傳來的參數
props: (propsRouter) => {
// console.log('props >router', propsRouter)
// 可以return query 也可以return params支持兩種傳參方式
return propsRouter.query
},
// 多級嵌套 建議用query傳參
children: [
{
path: 'childA',
name: 'ChildA',
component: () => import('@/views/Home/ChildA.vue'),
},
]
},
{
path: 'lxb/:id/:title', // 提前定義params參數(可以定義多個)
name: 'Lxb',
component: () => import('@/views/Home/Lxb.vue'),
},
]
},
]
export const router = createRouter({
// 路由的history模式,共有三種模式,
// createWebHistory、createWebHashHistory、createMemoryHistory
history: createWebHashHistory(),// history: createWebHistory(),
// 路由配置
routes,
// 是否嚴格匹配路由
strict: true,
// 路由跳轉完成后,頁面滾動行為
scrollBehavior: () => ({ left: 0, top: 0 }),
})
import { router } from './route/index'
import { createApp } from 'vue'
const app = createApp(App)
app.use(router).mount('#app')
<template>
<router-view />
</template>
<script>
import { defineComponent } from 'vue'
// vue3.0版本語法
export default defineComponent({
name: 'App',
})
</script>
<template>
<div class="home">
<h2>首頁{{ title }}</h2>
<!-- 模擬有權限時顯示 -->
<div v-if="roles.includes(role)">
<h2>嵌套路由</h2>
<router-link to="/home/lx">push跳轉到/home/lx頁面</router-link>
<br>
<!-- 加了/就要寫全 /home/lxb -->
<router-link replace to="/home/lxb/id:2/title:102">push跳轉到/home/lxb頁面</router-link>
<router-view></router-view>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, onMounted, toRefs, } from 'vue'
import { useRoute, useRouter } from 'vue-router'
export default defineComponent({
name: 'Home',
setup() {
const router = useRouter()
const route: any = useRoute()
const state = reactive({
title: '',
role: '', // 我的當前角色
roles: [''],
routerGo: (path) => {
if (path === 'lx') {
// query傳參可以用path 也可以用name: Lx
router.push({
path: path,
query: {
title: '101',
id: 1
}
})
// router.replace
} else {
// params傳參只能用name
router.replace({
// path: path + '/id:2/title:102',
name: 'Lxb',
params: {
title: '102',
id: 2
}
})
}
},
})
onMounted(() => {
console.log('/home', route)
state.title = route.meta.title
state.roles = route.meta.roles
// 模擬一個接口
setTimeout(() => {
const res = {
code: 200,
data: {
token: '123456',
userName: '吳彥祖',
role: 'admin'
}
}
state.role = res.data.role
}, 0)
})
return {
...toRefs(state)
}
}
})
</script>
<style lang="less" scoped>
.home {
color: pink;
font-size: 14px;
}
</style>
<template>
<div style="font-size: 14px;">
<h2>我是練習b{{ route?.params?.title }}頁面</h2>
<div>id:{{ route?.params?.id }}</div>
<button @click="routerGoBack">返回首頁</button>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, reactive, toRefs } from 'vue'
import { useRoute, useRouter } from 'vue-router'
// vue3.0語法
export default defineComponent({
name: 'Lxb',
setup() {
const route = useRoute()
const router = useRouter()
const state: any = reactive({
routerGoBack: () => {
router.replace('/home')
// 由replace跳轉進來的不可以使用router.go(-1) 路由棧是空的》回不到上一個路由
},
})
onMounted(() => {
console.log(route)
})
return {
route,
...toRefs(state)
}
},
})
</script>
<template>
<div style="font-size: 14px;">
<h2>我是練習{{ title }}頁面</h2>
<div>id:{{ id }}</div>
<div>props: {{ props }}</div>
<button @click="routerGoBack">返回上一頁</button>
<br>
<button @click="routerGo('/home/lx/childA')">去子路由childA</button>
<!-- <router-view></router-view> -->
<router-view />
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, reactive, toRefs } from 'vue'
import { useRoute, useRouter } from 'vue-router'
// vue3.0語法
export default defineComponent({
name: 'Lx',
props: {
id: {
type: String,
default: ''
},
title: {
type: String,
default: ''
},
},
setup(props) {
const route = useRoute()
const router = useRouter()
const state: any = reactive({
id: '',
title: '',
routerGoBack: () => {
router.go(-1) // go(-1)回到上一個路由
// 也可以用router.replace('/home')跳回指定頁
},
routerGo: (path) => {
router.push(path)
}
})
onMounted(() => {
console.log('lx route', route)
console.log('lx props', props)
if (route.query) {
state.id = route.query.id
state.title = route.query.title
}
})
return {
props,
...toRefs(state)
}
},
})
</script>
<template>
<div style="font-size: 14px;background: skyblue;">
<h3>我是ChildA組件</h3>
<h3>route.query:{{ route.query }}</h3>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, } from 'vue'
import { useRoute, useRouter } from 'vue-router'
// vue3.0語法
export default defineComponent({
name: 'ChildA',
setup() {
const router = useRouter()
const route = useRoute()
function goBack() {
router.go(-1)
}
onMounted(() => {
console.log(route)
})
// 可以在頁面銷毀前清除事件
// onUnmounted(() => {
// proxy.$mittBus.off('mittUserA')
// })
return {
route, goBack
}
},
})
</script>
嵌套一層的路由從原本/home跳入了/home/lxb 子路由頁面,點擊回到首頁。
先去到了第一層/home/lx子路由頁面,
再點擊去子路由childA按鈕>頁面效果:
進到了嵌套的第二層/home/lx/childA子路由頁面
點擊可返回上一頁/home/lx 再點擊可回到/home首頁。
歡迎關注我的原創文章:小伙伴們!我是一名熱衷于前端開發的作者,致力于分享我的知識和經驗,幫助其他學習前端的小伙伴們。在我的文章中,你將會找到大量關于前端開發的精彩內容。
學習前端技術是現代互聯網時代中非常重要的一項技能。無論你是想成為一名專業的前端工程師,還是僅僅對前端開發感興趣,我的文章將能為你提供寶貴的指導和知識。
在我的文章中,你將會學到如何使用HTML、CSS和JavaScript創建精美的網頁。我將深入講解每個語言的基礎知識,并提供一些實用技巧和最佳實踐。無論你是初學者還是有一定經驗的開發者,我的文章都能夠滿足你的學習需求。
此外,我還會分享一些關于前端開發的最新動態和行業趨勢。互聯網技術在不斷發展,新的框架和工具層出不窮。通過我的文章,你將會了解到最新的前端技術趨勢,并了解如何應對這些變化。
我深知學習前端不易,因此我將盡力以簡潔明了的方式解釋復雜的概念,并提供一些易于理解的實例和案例。我希望我的文章能夠幫助你更快地理解前端開發,并提升你的技能。
如果你想了解更多關于前端開發的內容,不妨關注我的原創文章。我會不定期更新,為你帶來最新的前端技術和知識。感謝你的關注和支持,我們一起探討交流技術共同進步,期待與你一同探索前端開發的奇妙世界!
#前端#
生成動態的HTML頁面,頁面中使用嵌入 Vue.js 語法可動態生成
1. {{xxxx}}雙大括號文本綁定
2. v-xxxx以v-開頭用于標簽屬性綁定,稱為指令
雙大括號語法{{}}
格式:{{表達式}}
作用:
使用在標簽體中,用于獲取數據
可以使用 JavaScript 表達式
一次性插值v-once
通過使用v-once指令,你也能執行一次性地插值,當數據改變時,插值處的內容不會更新
輸出HTML指令v-html
格式:v-html='xxxx'
作用:
如果是HTML格式數據,雙大括號會將數據解釋為普通文本,為了輸出真正的 HTML,你需要使用v-html指令。
Vue 為了防止 XSS 攻擊,在此指令上做了安全處理,當發現輸出內容有 script 標簽時,則不渲染
XSS 攻擊主要利用 JS 腳本注入到網頁中,讀取 Cookie 值(Cookie一般存儲了登錄身份信息),讀取到了發送到黑客服務器,從而黑客可以使用你的帳戶做非法操作。XSS 攻擊還可以在你進入到支付時,跳轉到釣魚網站。
元素綁定指令v-bind
完整格式:v-bind:元素的屬性名='xxxx'
縮寫格式::元素的屬性名='xxxx'
作用:將數據動態綁定到指定的元素上
事件綁定指令v-on
完整格式:v-on:事件名稱="事件處理函數名"
縮寫格式:@事件名稱="事件處理函數名"注意:@后面沒有冒號
作用:用于監聽 DOM 事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h3>1、{{}}雙大括號輸出文本內容</h3>
<!-- 文本內容 -->
<p>{{msg}}</p>
<!-- JS表達式 -->
<p>{{score + 1}}</p>
<h3>2、一次性插值</h3>
<p v-once>{{score + 1}}</p>
<h3>3、指令輸出真正的 HTML 內容 v-html</h3>
<p>雙大括號:{{contentHtml}}</p>
<!--
v-html:
1、如果輸出的內容是HTML數據,雙大括號將數據以普通文本方式進行輸出,為了輸出真正HTML數據,就需要使用v-html指定
2、為了防止XSS攻擊
-->
<p>v-html:<span v-html="contentHtml"></span></p>
<h3>4、v-bind屬性綁定指令</h3>
<img v-bind:src="imgUrl">
<img :src="imgUrl">
<a :href="tzUrl">跳轉</a>
<h3>5、事件綁定指令 v-on</h3> <input type="text" value="1" v-model="num"> <button @click='add'>點擊+1</button> </div> <script src="./node_modules/vue/dist/vue.js"></script> <script> var vm = new Vue({ el: '#app', data: { msg: "菜園子", score: 100, contentHtml: '<span style="color:red">此內容為紅色字體</span>', imgUrl: 'https://cn.vuejs.org/images/logo.png', tzUrl: 'https://www.baidu.com/', num : 10 }, methods: { add: function(){ console.log('add被調用') this.num ++ } }, }) </script></body></html>
git源碼地址:https://github.com/caiyuanzi-song/vue-demo.git
*請認真填寫需求信息,我們會在24小時內與您取得聯系。