欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue實(shí)現(xiàn)面包屑導(dǎo)航的正確方式

 更新時間:2023年06月20日 16:45:51   作者:小沈陽  
面包屑導(dǎo)航(BreadcrumbNavigation)這個概念來自童話故事“漢賽爾和格萊特”,它的作用是告訴訪問者他們在網(wǎng)站中的位置以及如何返回,本文為大家介紹了實(shí)現(xiàn)面包屑導(dǎo)航的正確方式,需要的可以參考一下

前言

面包屑導(dǎo)航(BreadcrumbNavigation)這個概念來自童話故事“漢賽爾和格萊特”,當(dāng)漢賽爾和格萊特穿過森林時,不小心迷路了,但是他們發(fā)現(xiàn)沿途走過的地方都撒下了面包屑,讓這些面包屑來幫助他們找到回家的路。所以,面包屑導(dǎo)航的作用是告訴訪問者他們在網(wǎng)站中的位置以及如何返回。

正如童話故事里的面包屑的作用,網(wǎng)站中的面包屑組件是為了告訴我們在網(wǎng)站中的位置。

然而,在看了一些 admin 項目后,發(fā)現(xiàn)面包屑的使用并不符合邏輯。

以 82k+ star 的 vue-element-admin 為例:

我們發(fā)現(xiàn)點(diǎn)擊某篇文章的編輯后,導(dǎo)航路徑從 首頁/綜合實(shí)例/文章列表 變?yōu)?首頁/綜合實(shí)例/編輯文章,而用戶正確的路徑是 首頁/綜合實(shí)例/文章列表/編輯文章。

分析 vue-element-admin 這種行為的原因

這里貼上其官網(wǎng)自動生成面包屑的代碼:

function getBreadcrumb() {
  // only show routes with meta.title
  let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
  const first = matched[0]
  if (!this.isDashboard(first)) {
    matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched)
  }
  this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
}

我們可以發(fā)現(xiàn)作者用到了 $route.matched,它的作用是:一個路由匹配到的所有路由記錄會暴露為 $route 對象(還有在導(dǎo)航守衛(wèi)中的路由對象)的 $route.matched 數(shù)組。

那么我看來看看其路由是如何注冊的:

可以看到列表和編輯被注冊到了同一級,matched 最后自然不會包含列表這一級。而且我們可以看到完全使用 matched 的缺點(diǎn):

圖中有一級綜合實(shí)例,這個路徑是因為在路由注冊時,它與列表或者編輯頁面形成了上下級關(guān)系。

所以,如果你的系統(tǒng)可以接收這個效果,可以參考 vue-element-admin 的行為。

怎么生成正確的路徑

至于怎么生成正確的路徑,如:首頁/綜合實(shí)例/文章列表/編輯文章。

我的方案是:每個頁面都寫自己的面包屑路徑!

這是最靈活,適應(yīng)性最強(qiáng)的一種方式了,當(dāng)然缺點(diǎn)也非常明顯,如果你的頁面很多,那改動的成本將會非常高。

所以,我又研究了第二種方式,它依舊是依賴于路由數(shù)據(jù)生成的。

當(dāng)然前面我們已經(jīng)知道了 router 注冊的數(shù)組,只能表示組件在頁面結(jié)構(gòu)上的一些父子關(guān)系,并不能正確表示用戶訪問的路徑。

所以我們需要額外維護(hù)一份,表示頁面訪問關(guān)系的樹形結(jié)構(gòu)(可以是環(huán)形,但是代碼需要額外處理,且不一定能表示正確的用戶訪問路徑,我們此次不討論)。

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import ListView from '@/views/ListView.vue'
import EditView from '@/views/EditView.vue'
import {useBreadcrumbStore} from "@/store/useBreadcrumbStore";
import DetailView from "@/views/DetailView.vue";
import _ from "lodash";
import ForthView from "@/views/ForthView.vue";
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      meta: {
        title: '首頁'
      },
      component: HomeView
    },
    {
      path: '/list',
      name: 'list',
      meta: {
        title: '列表'
      },
      component: ListView
    },
    {
      path: '/detail',
      name: 'detail',
      meta: {
        title: '詳情',
      },
      component: DetailView
    },
    {
      path: '/forth',
      name: 'forth',
      meta: {
        title: '第四級頁面',
      },
      component: ForthView,
    },
    {
      path: '/edit',
      name: 'edit',
      meta: {
        title: '編輯'
      },
      component: EditView
    },
    {
      path: '/about',
      name: 'about',
      meta: {
        title: '關(guān)于'
      },
      component: () => import('../views/AboutView.vue')
    }
  ]
})
const breadcrumbsStruct = [
  {
    name: 'home',
    children: [
      {
        name: 'list',
        children: [
          {
            name: 'edit'
          },
          {
            name: 'detail',
            children: [
              {
                name: 'forth',
              },
            ],
          }
        ]
      }
    ]
  },
  {
    name: 'about'
  }
]
router.afterEach((to) => {
  const target = to.name;
  const data: string[] = []
  let finalData = data;
  function dfs(arr: any[]) { // 在 breadcrumbsStruct 查找 target,且記錄下樹上的路徑
    if (!arr || !arr.length) {
      return;
    }
    for (let i=0; i<arr.length; i++) {
      const item = arr[i];
      data.push(item.name);
      if (item.name === target) {
        finalData = _.cloneDeep(data);
        break;
      }
      // 向深一級查找,查不到應(yīng)該回溯
      dfs(item.children);
      data.pop();
    }
  }
  dfs(breadcrumbsStruct);
  const routeList = router.getRoutes();
  const routeInfoList = finalData.map(item => {
      const info = routeList.find(r => r.name === item);
      if (info) {
        return info;
      } else {
        console.error('構(gòu)建路徑失敗');
      }
  });
  const store = useBreadcrumbStore();
  store.setBreadcrumbs(routeInfoList);
})
export default router

出了 router 的注冊外,額外維護(hù)一份 breadcrumbsStruct 數(shù)據(jù),其中 name 用于 router 中注冊的頁面匹配,為了方便匹配,規(guī)定它是不能重復(fù)的。children 表示從這個頁面可以打開哪些頁面。

afterEach 路由鉤子中,我們利用回溯算法生成面包屑數(shù)據(jù)。

完整的工程代碼在此處。

效果演示

頁面做的比較簡陋,但是我需要的效果達(dá)到了。

總結(jié)

最后的方案,需要額外維護(hù)一份數(shù)據(jù),這是需要成本的,但是這個成本可控。

面包屑導(dǎo)航屬于項目中的小細(xì)節(jié),一般不會引起重視,但是仔細(xì)想想,諸如 vue-element-admin 的實(shí)現(xiàn)確實(shí)生成的不是真正的用戶訪問路徑。

到此這篇關(guān)于Vue實(shí)現(xiàn)面包屑導(dǎo)航的正確方式的文章就介紹到這了,更多相關(guān)Vue面包屑內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用Vue3和Plotly.js繪制動態(tài)3D圖表的示例代碼

    使用Vue3和Plotly.js繪制動態(tài)3D圖表的示例代碼

    在數(shù)據(jù)可視化應(yīng)用中,需要將數(shù)據(jù)動態(tài)加載到圖表中并進(jìn)行實(shí)時更新,本文將展示如何使用Plotly.js和Vue.js實(shí)現(xiàn)這一功能,從加載外部數(shù)據(jù)到創(chuàng)建交互式圖表,文中有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下
    2024-06-06
  • vue3.0 加載json的方法(非ajax)

    vue3.0 加載json的方法(非ajax)

    這篇文章主要介紹了vue3.0 加載json的方法(非ajax),幫助大家更好的理解和學(xué)習(xí)vue,感興趣的朋友可以了解下
    2020-10-10
  • 解決vant-UI庫修改樣式無效的問題

    解決vant-UI庫修改樣式無效的問題

    這篇文章主要介紹了解決vant-UI庫修改樣式無效的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • vue項目同時兼容pc和移動端的解決方式

    vue項目同時兼容pc和移動端的解決方式

    我們經(jīng)常在項目中會有支持pc與手機(jī)端需求,下面這篇文章主要給大家介紹了關(guān)于vue項目同時兼容pc和移動端的解決方式,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • vue移動端自適應(yīng)適配問題詳解

    vue移動端自適應(yīng)適配問題詳解

    這篇文章主要介紹了vue移動端自適應(yīng)適配問題,本文通過實(shí)例代碼詳解給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-04-04
  • 如何使用vue-pdf-embed實(shí)現(xiàn)PDF在線預(yù)覽

    如何使用vue-pdf-embed實(shí)現(xiàn)PDF在線預(yù)覽

    vue-pdf-embed是一個基于Vue.js的插件,專門用于在Vue應(yīng)用中嵌入和展示PDF文件,本文將使用vue-pdf-embed實(shí)現(xiàn)PDF在線預(yù)覽功能,有需要的小伙伴可以參考一下
    2025-03-03
  • Vue.js基礎(chǔ)知識匯總

    Vue.js基礎(chǔ)知識匯總

    Vue.js 專注于 MVVM 模型的 ViewModel 層。它通過雙向數(shù)據(jù)綁定把 View 層和 Model 層連接了起來。Vue.js和其他庫相比是一個小而美的庫,作者的主要目的是通過一個盡量簡單的 API 產(chǎn)生可反映的數(shù)據(jù)綁定和可組合的視圖組件,感覺作者的思路非常清晰。
    2016-04-04
  • vue3+ts+echarts實(shí)現(xiàn)按需引入和類型界定方式

    vue3+ts+echarts實(shí)現(xiàn)按需引入和類型界定方式

    這篇文章主要介紹了vue3+ts+echarts實(shí)現(xiàn)按需引入和類型界定方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • vue3限制table表格選項個數(shù)的解決方法

    vue3限制table表格選項個數(shù)的解決方法

    這篇文章主要為大家詳細(xì)介紹了vue3限制table表格選項個數(shù)的解決方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 詳解.vue文件中style標(biāo)簽的幾個標(biāo)識符

    詳解.vue文件中style標(biāo)簽的幾個標(biāo)識符

    這篇文章主要介紹了詳解.vue文件中style標(biāo)簽的幾個標(biāo)識符,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07

最新評論