vue3自己封裝面包屑功能組件的幾種方式
前言
面包屑導(dǎo)航可以將瀏覽過(guò)的頁(yè)面記錄下來(lái),方便很快速的跳轉(zhuǎn)回某一個(gè)頁(yè)面,本文介紹了幾種自己封裝面包屑組件的方式,我們一起來(lái)看看如何實(shí)現(xiàn)的吧~
一、為什么需要面包屑?
面包屑導(dǎo)航(BreadcrumbNavigation)這個(gè)概念來(lái)自童話故事“漢賽爾和格萊特”,當(dāng)漢賽爾和格萊特穿過(guò)森林時(shí),不小心迷路了,但是他們發(fā)現(xiàn)在沿途走過(guò)的地方都撒下了面包屑,讓這些面包屑來(lái)幫助他們找到回家的路。
看完上面的介紹,相信各位已經(jīng)理解了面包屑組件的使用場(chǎng)景了。對(duì)的,沒(méi)錯(cuò),是用來(lái)記錄我們點(diǎn)擊了哪些頁(yè)面,方便我們?cè)俜祷刂澳骋粋€(gè)頁(yè)面。
當(dāng)網(wǎng)頁(yè)進(jìn)行了多次跳轉(zhuǎn)后,用戶可能早就已經(jīng)暈頭轉(zhuǎn)向了。作為程序猿的我們可能通過(guò)地址欄參數(shù)還可以分清楚當(dāng)前處于哪一個(gè)位置,終歸網(wǎng)頁(yè)是要展示給用戶。用戶來(lái)使用的話,沒(méi)有面包屑導(dǎo)航的話,可能就對(duì)網(wǎng)頁(yè)產(chǎn)生了抵觸心理,使用面包屑導(dǎo)航將每次跳轉(zhuǎn)的頁(yè)面記錄下來(lái),可以很好解決這一問(wèn)題。
二、初級(jí)封裝
1. 實(shí)現(xiàn)思路
準(zhǔn)備頁(yè)面結(jié)構(gòu)和樣式,需要用到字體圖標(biāo)
在public目錄下的index.html中引入cdn的字體圖標(biāo)資源
<link rel="stylesheet" rel="external nofollow" >
將需要外部傳入的值定義為自定義屬性
將外部寫(xiě)在標(biāo)簽內(nèi)部的內(nèi)容放置在默認(rèn)插槽中
2. 代碼演示
在src/components目錄下新建bread-crumbs.vue文件,公用的組件放在這個(gè)目錄下統(tǒng)一管理,文件名可自定義。
代碼如下(示例):
<template>
<div class='bread-crumbs'>
<div class="bread-crumbs-item">
<RouterLink to="/">首頁(yè)</RouterLink>
</div>
<i class="iconfont icon-angle-right"></i>
<div v-if="parentName" class="bread-crumbs-item">
<RouterLink v-if="parentPath" :to="parentPath">{{parentName}}</RouterLink>
<span v-else>{{parentName}}</span>
</div>
<i v-if="parentName" class="iconfont icon-angle-right"></i>
<div class="bread-crumbs-item">
<span>
<slot/>
</span>
</div>
</div>
</template>
<script>
export default {
name: 'BreadCrumbs',
props: {
parentName: {
type: String,
default: ''
},
parentPath: {
type: String,
default: ''
}
}
}
</script>
<style scoped lang='less'>
.bread-crumbs{
display: flex;
padding: 25px 10px;
&-item {
a {
text-decoration: none;
color: #666;
transition: all .4s;
&:hover {
color: #27ba9b;
}
}
}
i {
font-size: 12px;
font-style: normal;
margin-left: 5px;
margin-right: 5px;
line-height: 22px;
}
}
</style>
在src/components目錄下新建index.js文件,將封裝好的全局組件進(jìn)行注冊(cè)
import BreadCrumbs from './bread-crumbs'
export default {
install (app) {
app.component(BreadCrumbs.name, BreadCrumbs)
}
}
在main.js中注冊(cè)為插件
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// 導(dǎo)入并注冊(cè)
import myUI from './components'
createApp(App).use(store).use(router).use(myUI).mount('#app')
3. 使用
傳入公共組件需要的值
代碼如下(示例):
<template>
<div class="home-banner">
<bread-crumbs parentPath="/xxx" parentName="電器">空調(diào)</bread-crumbs>
</div>
</template>
<script>
export default {
name: 'App',
setup() {
}
}
</script>
4. 不足
只能滿足基本需求,超過(guò)二級(jí)導(dǎo)航后就無(wú)法使用。
三、進(jìn)階封裝
1. 實(shí)現(xiàn)思路
參考elementUI面包屑組件代碼
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首頁(yè)</el-breadcrumb-item>
<el-breadcrumb-item><a href="/" rel="external nofollow" >活動(dòng)管理</a></el-breadcrumb-item>
<el-breadcrumb-item>活動(dòng)列表</el-breadcrumb-item>
<el-breadcrumb-item>活動(dòng)詳情</el-breadcrumb-item>
</el-breadcrumb>
將每一個(gè)導(dǎo)航封裝為一個(gè)組件
2. 代碼演示
在上一步封裝的基礎(chǔ)上繼續(xù)改進(jìn)代碼
代碼如下(示例):
在src/component目錄下新建bread-crumbs-item組件,文件名可以自定義。
<template>
<div class="bread-crumbs-item">
<RouterLink v-if="to" :to="to"><slot /></RouterLink>
<span v-else><slot /></span>
<i class="iconfont icon-angle-right"></i>
</div>
</template>
<script>
export default {
name: 'BreadCurmbsItem',
props: {
to: {
type: [String, Object]
}
}
}
</script>
還是在src/components目錄下的index.js中注冊(cè)為全局組件
import BreadCrumbs from './bread-crumbs'
import BreadCrumbsItem from './bread-crumbs-item'
export default {
install (app) {
app.component(BreadCrumbs.name, BreadCrumbs)
app.component(BreadCrumbsItem .name, BreadCrumbsItem )
}
}
修改BreadCrumbs.vue中代碼,將導(dǎo)航的每一項(xiàng)放置在默認(rèn)插槽中
<template>
<div class='bread-crumbs'>
<slot />
</div>
</template>
<script>
export default {
name: 'BreadCrumbs'
}
</script>
<style scoped lang='less'>
.bread-crumbs {
display: flex;
padding: 25px 10px;
:deep(&-item) {
a {
text-decoration: none;
color: #666;
transition: all 0.4s;
&:hover {
color: #27ba9b;
}
}
}
:deep(i) {
font-style: normal;
font-size: 12px;
margin-left: 5px;
margin-right: 5px;
line-height: 22px;
}
}
</style>
3. 使用
使用的時(shí)候,有多少個(gè)二級(jí)導(dǎo)航就使用幾個(gè)BreadCrumbsItem
代碼如下(示例):
<template>
<div class="home-banner">
<!-- 面包屑 -->
<BreadCrumbs>
<BreadCrumbsItem to="/">首頁(yè)</BreadCrumbsItem>
<BreadCrumbsItem to="/xxx">電器</BreadCrumbsItem>
<BreadCrumbsItem >空調(diào)</BreadCrumbsItem>
</BreadCrumbs>
</div>
</template>
<script>
export default {
name: 'App',
setup() {
}
}
</script>
4. 不足
在最后一個(gè)導(dǎo)航后面會(huì)有多余的一個(gè)>指示標(biāo)識(shí)

四、高階封裝
1. 思路
終極版,使用render函數(shù)自己進(jìn)行拼接創(chuàng)建。
render render選項(xiàng)與h函數(shù)
指定組件顯示的內(nèi)容:new Vue({選項(xiàng)})
- el 選項(xiàng),通過(guò)一個(gè)選擇器找到容器,容器內(nèi)容就是組件內(nèi)容
- template 選項(xiàng),<div>組件內(nèi)容</div> 作為組件內(nèi)容
- render選項(xiàng),它是一個(gè)函數(shù),函數(shù)回默認(rèn)傳人createElement的函數(shù)(h),這個(gè)函數(shù)用來(lái)創(chuàng)建結(jié)構(gòu),再render函數(shù)返回渲染為組件內(nèi)容。它的優(yōu)先級(jí)更高。
2. 代碼演示
修改BreadCurmbsItem組件內(nèi)的代碼
<template>
<div class="bread-crumbs-item">
<RouterLink v-if="to" :to="to"><slot /></RouterLink>
<span v-else><slot /></span>
</div>
</template>
<script>
export default {
name: 'BreadCurmbsItem',
props: {
to: {
type: [String, Object]
}
}
}
</script>
修改BreadCrumbs.vue中的代碼
代碼示例(如下):
<script>
import { h } from 'vue'
export default {
name: 'BreadCrumbs',
render () {
// 用法
// 1. template 標(biāo)簽去除,單文件組件
// 2. 返回值就是組件內(nèi)容
// 3. vue2.0 的h函數(shù)傳參進(jìn)來(lái)的,vue3.0 的h函數(shù)導(dǎo)入進(jìn)來(lái)
// 4. h 第一個(gè)參數(shù) 標(biāo)簽名字 第二個(gè)參數(shù) 標(biāo)簽屬性對(duì)象 第三個(gè)參數(shù) 子節(jié)點(diǎn)
// 需求
// 1. 創(chuàng)建bread-crumbs父容器
// 2. 獲取默認(rèn)插槽內(nèi)容
// 3. 去除bread-crumbs-item組件的i標(biāo)簽,因該由render函數(shù)來(lái)組織
// 4. 遍歷插槽中的item,得到一個(gè)動(dòng)態(tài)創(chuàng)建的節(jié)點(diǎn),最后一個(gè)item不加i標(biāo)簽
// 5. 把動(dòng)態(tài)創(chuàng)建的節(jié)點(diǎn)渲染再bread-crumbs標(biāo)簽中
const items = this.$slots.default()
const dymanicItems = []
items.forEach((item, i) => {
dymanicItems.push(item)
if (i < (items.length - 1)) {
dymanicItems.push(h('i', { class: 'iconfont icon-angle-right' }))
}
})
return h('div', { class: 'bread-crumbs' }, dymanicItems)
}
}
</script>
<style lang='less'>
// 將scope屬性去除,目的是為了樣式穿透至item組件中
.bread-crumbs {
display: flex;
padding: 25px 10px;
&-item {
a {
text-decoration: none;
color: #666;
transition: all .4s;
&:hover {
color: #27ba9b;
}
}
}
i {
font-size: 12px;
margin-left: 5px;
margin-right: 5px;
line-height: 22px;
// 樣式的方式,不合理
// &:last-child {
// display: none;
// }
}
}
</style>
3. 使用
這個(gè)方式封裝后,讓全局組件的復(fù)用性更強(qiáng)了,強(qiáng)烈推薦使用
<template>
<div class="home-banner">
<!-- 面包屑 -->
<BreadCrumbs>
<BreadCrumbsItem to="/">首頁(yè)</BreadCrumbsItem>
<BreadCrumbsItem to="/xxx">電器</BreadCrumbsItem>
<BreadCrumbsItem to="/xxx/xx">空調(diào)</BreadCrumbsItem>
<BreadCrumbsItem >遙控器</BreadCrumbsItem>
</BreadCrumbs>
</div>
</template>
<script>
export default {
name: 'App',
setup() {
}
}
</script>

可以看到這樣封裝后,咱們自己封裝的面包屑導(dǎo)航已經(jīng)支持多級(jí)導(dǎo)航了。而且最后一個(gè)導(dǎo)航后面的>指示標(biāo)識(shí)也沒(méi)有了。
五、使用jsx優(yōu)化
可以將高階寫(xiě)法中的功能代碼使用jsx的方式進(jìn)行重寫(xiě),jsx寫(xiě)出來(lái)的代碼更加的簡(jiǎn)潔明了。
export default {
name: 'BreadCrumbs',
render () {
// vue2的render函數(shù)的形參是 h 函數(shù)
// vue3中h函數(shù)是導(dǎo)入的
// createElement(標(biāo)簽名稱, 標(biāo)簽的屬性, 標(biāo)簽的子元素)
// console.dir(this.$slots.default())
// 獲取XtxBread組件的所有的插槽里面填充組件實(shí)例
const items = this.$slots.default()
const results = []
items.forEach((item, index) => {
results.push(item)
// 手動(dòng)生成一個(gè)i圖標(biāo),添加到面包屑項(xiàng)目的后面
if (index < items.length - 1) {
results.push(<i className='iconfont icon-angle-right'></i>)
}
})
return <div className='bread-crumbs'>{results}</div>
}
}
總結(jié)
功能雖然很小,但是涵蓋的知識(shí)點(diǎn)很多,以上代碼均已在本地測(cè)試
到此這篇關(guān)于vue3自己封裝面包屑功能組件的文章就介紹到這了,更多相關(guān)vue3封裝面包屑功能組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
前端虛擬滾動(dòng)列表實(shí)現(xiàn)代碼(vue虛擬列表)
前端的性能瓶頸那就是頁(yè)面的卡頓,當(dāng)然這種頁(yè)面的卡頓包含了多種原因,下面這篇文章主要給大家介紹了關(guān)于前端虛擬滾動(dòng)列表實(shí)現(xiàn)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-06-06
Vue基礎(chǔ)學(xué)習(xí)之項(xiàng)目整合及優(yōu)化
這篇文章主要給大家介紹了關(guān)于Vue基礎(chǔ)學(xué)習(xí)之項(xiàng)目整合及優(yōu)化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
Vue中獲取this.$refs為undefined的問(wèn)題
這篇文章主要介紹了Vue中獲取this.$refs為undefined的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05
vue+echarts動(dòng)態(tài)更新數(shù)據(jù)及數(shù)據(jù)變化重新渲染方式
這篇文章主要介紹了vue+echarts動(dòng)態(tài)更新數(shù)據(jù)及數(shù)據(jù)變化重新渲染方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
Vue中實(shí)現(xiàn)父子組件雙向數(shù)據(jù)流的三種方案分享
通常情況下,父子組件的通信都是單向的,或父組件使用props向子組件傳遞數(shù)據(jù),或子組件使用emit函數(shù)向父組件傳遞數(shù)據(jù),本文將嘗試講解Vue中常用的幾種雙向數(shù)據(jù)流的使用,需要的朋友可以參考下2023-08-08
Vue.js中provide/inject實(shí)現(xiàn)響應(yīng)式數(shù)據(jù)更新的方法示例
這篇文章主要介紹了Vue.js中provide/inject實(shí)現(xiàn)響應(yīng)式數(shù)據(jù)更新,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
使用Vue3實(shí)現(xiàn)在瀏覽器端進(jìn)行zip文件壓縮
在前端開(kāi)發(fā)中,我們時(shí)常需要處理文件上傳和下載的功能,本文主要和大家分享一下如何使用Vue3和JSZip庫(kù)在瀏覽器端實(shí)現(xiàn)zip文件壓縮,需要的可以參考下2024-05-05

