日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

開始切入正題之前,有必要告知大家一下,這篇文章可能有一些深度,初學(xué)者可能理解會有些吃力。我會盡量把復(fù)雜問題簡單化,爭取讓每個閱讀的童鞋們都能看得懂。希望你對element-ui,vue-router,KeepAlive組件有一點(diǎn)了解。現(xiàn)在,我們開始吧。

熟悉element-ui的童鞋們都知道,ElMenuItem和ElSubMenu都需要一個index屬性,該屬性必須是唯一的。現(xiàn)在,我們想把路由配置直接應(yīng)用于ElMenu,該如何確保index的唯一性呢?我們需要有一個生成唯一index的函數(shù)。如下是genKey函數(shù)的定義,是不是很簡單?

export const genKey = ((k = 1) => () => k++)()

現(xiàn)在,我們創(chuàng)建addRouteMetaKey函數(shù),該函數(shù)對路由樹進(jìn)行遞歸遍歷,為每一個路由配置的meta屬性動態(tài)添加key字段。這個函數(shù)很簡單,屬于最基礎(chǔ)的遞歸使用例子,我就不做太多解釋了。

提示:數(shù)組的forEach方法不是純函數(shù),因?yàn)樗懈弊饔茫詅orEach方法不能稱之為函數(shù)式編程工具。

/** @param {import('vue-router').RouteRecordRaw[]} routes */
const addRouteMetaKey = routes => {
  routes.forEach(route => {
    if (route.meta) {
      route.meta.key = genKey()
    } else {
      route.meta = { key: genKey() }
    }
    route.children && addRouteMetaKey(route.children)
  })
  return routes
}

通過addRouteMetaKey函數(shù),我們可以把路由的meta.key作為index的值了。

現(xiàn)在,我們想實(shí)現(xiàn)另一個功能,就是基于標(biāo)簽頁的路由組件緩存控制。使用過Vuejs KeepAlive組件的童鞋們,應(yīng)該多多少少都遇到一些坑吧?在我們的項(xiàng)目中,有一個頂部標(biāo)簽頁導(dǎo)航,每個tab項(xiàng)對應(yīng)一個url,以每個url對應(yīng)路由的title作為tab項(xiàng)標(biāo)題,當(dāng)切換tab的時候加載緩存中的url對應(yīng)的路由組件,關(guān)閉tab項(xiàng),下次打開該路由url,重新掛載對應(yīng)的路由組件,而不是從緩存中加載。

當(dāng)路由層級不確定的時候,KeepAlive會變的難以手動控制。所以,我劍走偏鋒,嘗試了一種簡單的解決方案,實(shí)踐證明:這是非常有效的。我的方案就是把無限層級的路由樹轉(zhuǎn)化為一維數(shù)組。通過為meta添加必要的字段,進(jìn)行頁面結(jié)構(gòu)個性化定制。

我們需要把每層路由配置的path轉(zhuǎn)化為全路徑,所以需要一個函數(shù):getRouteFullPath,該函數(shù)定義如下:

/**
 * 獲取路由全路徑
 * @description 如果path以 / 開頭(屬于絕對路徑),則直接返回,否則拼接路徑
 * @param {string} path
 * @param {string} parentPath
 */
export const getRouteFullPath = (path, parentPath) => {
  return !parentPath || path.startsWith('/') ? path : joinPath(parentPath, path)
}

getRouteFullPath函數(shù)中使用到的joinPath函數(shù)用于將多個路徑字符串拼接為1個完整的路徑,定義如下:

/** @param {string[]} paths */
export const joinPath = (...paths) => {
  const j = '/'
  const [a, ...b] = paths
  return (a.endsWith('/') ? a.replace(/(/+)$/gm, j) : a + j) + b.map(_ => _.replace(/^(/+)|(/+)$/gm, '')).join(j)
}

現(xiàn)在,我們把路由樹轉(zhuǎn)化為一維數(shù)組。我們定義toFlatRoutes函數(shù),該函數(shù)使用了數(shù)組的reduce方法對路由樹進(jìn)行聚合遞歸,將路由配置中的path屬性的值替換為全路徑,還順便給路由配置添加了name屬性,返回一個新的一維路由配置數(shù)組。這是函數(shù)式編程和遞歸結(jié)合的一個例子。

/**
 * @param {import('vue-router').RouteRecordRaw[]} routes
 * @returns {import('vue-router').RouteRecordRaw[]}
*/
const toFlatRoutes = (routes, parentPath) => {
  return routes.reduce((t, r) => {
    const path = getRouteFullPath(r.path, parentPath)
    return [
      ...t,
      ...(r.children
          ? toFlatRoutes(r.children, path)
          : [{ ...r, path, name: r.name || `name-${genKey()}` }]
        )
    ]
  }, [])
}

以上,我們解決了KeepAlive的緩存控制問題;現(xiàn)在,我們又有了一個新的用戶體驗(yàn)上的需求,就是我們想根據(jù)url對應(yīng)的路由,自動展開該路由meta.key所屬的側(cè)邊菜單;我們通過查閱element-ui文檔得知,ElMenu有一個open方法,接收index作為參數(shù),展開index對應(yīng)的菜單。

現(xiàn)在的問題是,我們的路由對應(yīng)的index是ElMenuItem的,而路由樹已經(jīng)被我們轉(zhuǎn)化為了一維數(shù)組,通過路由的matched字段是得不到我們想要的菜單index的。所以,我們需要遍歷原始路由樹

如下代碼,我們定義getMenuKey函數(shù),該函數(shù)接收的參數(shù)為route對象。如果路由存在,我們進(jìn)行查找。首先進(jìn)行簡單查找,如果找到一個菜單menu,則返回該菜單的meta.key;如果簡單查找無果,則對路由樹進(jìn)行遞歸查找;這是函數(shù)式編程和遞歸結(jié)合的另一個例子。

/**
 * @param {import('vue-router').RouteRecordRaw} item
 * @returns {number|undefined}
*/
export const getMenuKey = item => {
  if (item) {
    const menu = state.menus.find(m => item.path.startsWith(m.path))
    if (menu) {
      return menu.meta.key
    }
    const itemKey = item.meta.key
    return (function findFunc (menus) {
      /** @param {import('vue-router').RouteRecordRaw} m */
      const fn = m => m.meta.key === itemKey ? true : m.children && m.children.some(fn)
      const curMenu = menus.find(fn)
      return curMenu && curMenu.meta.key
    })(state.menus) // state是響應(yīng)式對象,定義:const state = reactive({ menus: [] })
  }
}

現(xiàn)在,我們大功告成了;以上就是本節(jié)的知識點(diǎn),童鞋們理解了嗎?只要我們熟悉遞歸的使用,其實(shí)操作樹很簡單。如果大家還有不懂的,可以評論區(qū)問我。感謝閱讀!

分享到:
標(biāo)簽:函數(shù) JS
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定