1. 程式人生 > >ant design pro 程式碼學習(三) ----- 選單資料分析

ant design pro 程式碼學習(三) ----- 選單資料分析

1、getSelectedMenuKeys 獲取選中的選單的key

  getSelectedMenuKeys = () => {
    const {location: {pathname}} = this.props;
    return getMeunMatchKeys(this.flatMenuKeys, urlToList(pathname));
  };

   getSelectedMenuKeys中涉及到getMeunMatchKeys()、this.flatMenuKeys、urlToList(),下邊分別對其進行分析。

this.flatMenuKeys = getFlatMenuKeys(props.menuData);
.....
export
const getFlatMenuKeys = menu => menu.reduce((keys, item) => { keys.push(item.path); if (item.children) { return keys.concat(getFlatMenuKeys(item.children)); } return keys; }, []);

  getFlatMenuKeys通過對props.menuData資料遞迴呼叫,返回props.menuData中所有層級資料的path值(Array型別),其中path為完整的路徑值(getMenuData()已處理過)

export function urlToList(url) {
  //filter(i => i) 去除空
  const urllist = url.split('/').filter(i => i);
  return urllist.map((urlItem, index) => {
    return `/${urllist.slice(0, index + 1).join('/')}`;
  });
}

  將pathname傳入到urlToList方法中,urlToList首先對url用’/’分割,filter方法對空值進行處理(分割後第一個元素為空)。返回一級路徑、二級路徑…依次類推。例如當前pathname為/A/B時,則返回[‘/A’,’/A/B’]

export const getMeunMatchKeys = (flatMenuKeys, paths) =>
  paths.reduce((matchKeys, path) => (
    matchKeys.concat(
      flatMenuKeys.filter(item => pathToRegexp(item).test(path))
    )), []);

  getMeunMatchKeys對flatMenuKeys、paths做雙重迴圈,其中pathToRegexp會對/path/:id等資料做處理,會匹配/path路徑。返回值為,flatMenuKeys中包含的paths元素(返回型別Array)。

  綜上所述,getFlatMenuKeys返回當前路由的pathname對應在flatMenuKeys中匹配項。例如當前pathname=’/dashboard/analysis’(有效路由),則返回[‘/dashboard’,’/dashboard/analysis’];當前pathname=’/aaa’(無效路由),則返回[],因為flatMenuKeys找不到匹配項。

2、handleOpenChange 切換選單時,更改選中的選單key

isMainMenu = key => {
    return this.menus.some(item => key && (item.key === key || item.path === key));
};

handleOpenChange = openKeys => {
    const lastOpenKey = openKeys[openKeys.length - 1];
    const moreThanOne = openKeys.filter(openKey => this.isMainMenu(openKey)).length > 1;

    this.setState({
      openKeys: moreThanOne ? [lastOpenKey] : [...openKeys],
    });
};

......
//Menu元件中onOpenChange事件
onOpenChange={this.handleOpenChange}

   isMainMenu用來檢測當前路徑是否為一級選單路徑。

   由ant design中的Menu元件可知,onOpenChange事件的回撥方法中,傳入引數openKeys為當前多級路徑、將被開啟的路徑的集合。

  1. 如果當前路徑、即將開啟的路徑是一級選單間切換,則moreThanOne必為true,例如當前’/dashboard/analysis’,即將開啟’/list’,此時openKeys為[‘/dashboard’,’/dashboard/analysis’,’/list’],則openKeys為即將開啟的頁面的路由,即/list’;

  2. 如果是當前選單的子選單開啟,則moreThanOne為false,例如當前開啟的選單時’/list’(列表項),即將開啟’/list/search’(搜尋列表),則openKeys為[“/list”, “/list/search”],此時Menu元件會開啟:列表-搜尋列表;

  3. 如果,點選當前開啟的選單,則此時即為關閉選單,openKeys為[]。

  *注:結合getSelectedMenuKeys、handleOpenChange。對selectedKeys做了如下處理:如果根據當前路由資訊找不到匹配的選單項,則當前選中的選單項為解決要開啟的選單項。*

let selectedKeys = this.getSelectedMenuKeys();
if (!selectedKeys.length) {
  selectedKeys = [openKeys[openKeys.length - 1]];
}

3、getNavMenuItems 、getSubMenuOrItem獲取選單項入口方法

  getNavMenuItems獲取存在選單名稱(name)、且可見的選單(!item.hideInMenu)。其中getSubMenuOrItem根據當前的是否存在子選單返回或者

  getNavMenuItems = menusData => {
    if (!menusData) {
      return [];
    }
    return menusData
      .filter(item => item.name && !item.hideInMenu)
      .map(item => {
        // make dom
        const ItemDom = this.getSubMenuOrItem(item);
        return this.checkPermissionItem(item.authority, ItemDom);
      })
      .filter(item => item);
  };
 getSubMenuOrItem = item => {
    if (item.children && item.children.some(child => child.name)) {
      const childrenItems = this.getNavMenuItems(item.children);

      if (childrenItems && childrenItems.length > 0) {
        return (
          <SubMenu
            title={
              item.icon ? (
                <span>
                  {getIcon(item.icon)}
                  <span>{item.name}</span>
                </span>
              ) : (
                item.name
              )
            }
            key={item.path}
          >
            {childrenItems}
          </SubMenu>
        );
      }
      return null;
    } else {
      return <Menu.Item key={item.path}>{this.getMenuItemPath(item)}</Menu.Item>;
    }
  };

  第一次呼叫getSubMenuOrItem方法,

 <Menu>
 ......
  {this.getNavMenuItems(this.menus)}
</Menu>

有如下邏輯,遍及選單資料(一級選單):
1. 如果當前選單資料(item),不存在子選單或者子選單中不存在name屬性時,則判斷為當前選單項沒有子選單,返回Menu.Item;此時代表一級選單沒有子選單,則返回的Menu.Item直接作為

的子元素;
  1. 如果當前選單資料存在子選單,則對子選單呼叫getNavMenuItems方法,此處存在遞迴呼叫getSubMenuOrItem。繼續執行1、2。當前子選單如果沒有下一級子選單,則返回SubMenu - Menu.Item - SubMenu,如果存在繼續遞迴呼叫。此時一級選單已經確定含有子選單,所以遞迴的結果是作為SubMenu的子元素,當然SubMenu中也有可能包含SubMenu。

4、checkPermissionItem 獲取當前選單的許可權

  • 方法使用:
const ItemDom = this.getSubMenuOrItem(item);
return this.checkPermissionItem(item.authority, ItemDom);
  • 方法引用
  checkPermissionItem = (authority, ItemDom) => {
    if (this.props.Authorized && this.props.Authorized.check) {
      const {check} = this.props.Authorized;
      return check(authority, ItemDom);
    }
    return ItemDom;
  };

   由getSubMenuOrItem返回的是SubMenu或者Menu.Item元件,checkPermissionItem方法中的Authorized屬性是元件,由ant design pro 程式碼學習(一) —– 路由分析分析可知,this.props.Authorized.check() 接受三個引數:1、元件的許可權值;2、鑑權通過返回的元件;3、鑑權不通過返回的元件。方法內部會根據當前許可權值authority與currentAuthority對比,決定返回值。

   由menuData中的資料可知,當前選單資料中,除了賬戶(user)的authority為’guest’,其他均為undefined。而當前的許可權值currentAuthority是根據呼叫介面’/api/login/account’來確定的(具體在後續登入部分在分析)登入後不為’guest’(具體根據賬號型別為admin或者user)。

   check()中當傳入的authority為undefined時,則直接認為是鑑權通過。由於賬戶(user)相關的許可權為guest,不等於’admin’,此時返回undefined(因為鑑權未通過的元件引數未傳入)。getNavMenuItems()方法中通過Array.filter過濾掉undefined、null、‘’ 等元素。否則的話根據react官方文件api可知,在jsx中undefined會被渲染為空

,會生成無效空元素。

false,null,undefined,和 true 都是有效的的 children(子元素) 。但是並不會被渲染。 —– react文件-深入 JSX

5、getMenuItemPath 生成選單項

   根據選單資料中的path屬性,判斷是否含有https,如果有,則認為是連結,生成a標籤,如果沒有則認為系統內部頁面,則生成Link標籤。getIcon用於生成選單圖示 。

 getMenuItemPath = item => {
    const itemPath = this.conversionPath(item.path);
    const icon = getIcon(item.icon);
    const {target, name} = item;
    // Is it a http link
    if (/^https?:\/\//.test(itemPath)) {
      return (
        <a href={itemPath} target={target}>
          {icon}
          <span>{name}</span>
        </a>
      );
    }
    return (
      <Link
        to={itemPath}
        target={target}
        replace={itemPath === this.props.location.pathname}
        onClick={
          this.props.isMobile
            ? () => {
              this.props.onCollapse(true);
            }
            : undefined
        }
      >
        {icon}
        <span>{name}</span>
      </Link>
    );
  };

6、選單資料流程圖

這裡寫圖片描述

相關推薦

ant design pro 程式碼學習() ----- 選單資料分析

1、getSelectedMenuKeys 獲取選中的選單的key getSelectedMenuKeys = () => { const {location: {pathname}} = this.props; return g

ant design pro 程式碼學習(二) ----- 路由資料分析

  本章節包含路由資訊(common/router)、側邊欄選單資訊(common/menu)、基本路由(一級路由)UserLayout元件,BasicLayout元件、以及側邊欄SiderMenu元件中對資料的處理。主要涉及到以下幾個方法,分別逐個分析其功能。

ant design pro 程式碼學習(六) ----- 知識點總結2

1 、connect 多個model   以下為redux的API中對connect方法的定義: connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])  

【 專欄 】- ant design pro程式碼學習成果分享

ant design pro程式碼學習成果分享 專注web前端開發。對ant design pro的程式碼進行分析,包含路由、選單、元件封裝、資料mock、相關知識點的總結。後續還會繼續更新,希望我的點滴努力能給帶來一些技術提升。

2.Ant Design Pro的第一個選單

準備 正式開發前需要準備一個IDE,如果是用純記事本的大神請忽略 可以選Sublime和VsCode等,找個自己用過的順手的 反正我都沒用過,跟隨我軟的指令碼我就選VsCode把 在VSCode裡新增一個工程,選定上一章克隆下來的工程資料夾目錄 然後再儲存下工程檔案

Ant Design Pro使用技巧之mock資料地址改為伺服器地址

Ant Design Pro本身提供了較為強大的mock資料的功能。 然而,當如果是單人開發模式或者後臺已經開發完成的情況下,我們更希望在前端開發除錯過程中直接訪問後端服務的介面。 本文主要講述該技巧,即如何將mock資料地址改為伺服器地址 .roadhogrc.mock.js .r

ant design pro的採坑之旅 (動態建立選單、訪問mock資料、富文字編輯器)

       最近公司做一個後臺管理系統,猶豫半天還是想用ant design,後來發現他們有現成的腳手架 ant design pro ( github地址 ),果斷拉程式碼下來執行起來。 一:ant design pro 專案目錄結構和流程 整體目錄大概長這個樣子 

react+ant design pro 2.0+dva 後臺管理系統,學習筆記

1.如果你熟悉 HTML,那麼 JSX 對於你來說是沒有任何壓力的,因為 HTML 中的所有標籤,在 JSX 中都是支援的,基本上沒有學習成本,只有如下幾點略微的不同: class 屬性變為 className tabindex 屬性變為 tabIndex

ant design pro 新增一級選單和子選單

1.新建個檔案,我這個是複製其它自帶的檔案(list資料夾的TableList.js) 2.然後找到這個檔案 去配router 3.也是copy其它的,就是改一下名字和路徑檔案就好了

Ant Design Pro學習小結

在models的effects中直接用setTimeout函式會報錯,例如以下錯誤寫法: effects: { *update({ payload }, { call, put }) { const response = yield call(update, payload);

ant design pro 配置動態選單、許可權

import React, { Suspense } from 'react'; import { Layout } from 'antd'; import DocumentTitle from 'react-document-title'; import isEqual from 'lodash/isEq

Ant Design Pro學習手記

2.npm install出現問題:npm ERR! network connect ETIMEDOUT。    解決方法:npm install後再使用npm install no-proxy,此後專案可以正常啟動3.關於mock相關問題:.roadhogrc.mock.j

Ant Design Pro 選單icon修改或新增

//自己新增頁面 path: '/qrdata', name: 'qrdata', icon: 'qrcode', //原來的form頁面 path: '/form', icon: 'form

ant-design-pro 動態選單-路由詳解

開發十年,就只剩下這套架構體系了! >>>   

Ant Design Pro V5 從伺服器請求選單(typescript版)

## 【前言】 > 找了很多Admin模板,最後還是看中了AntDesignPro(下文簡寫antd pro)這個阿里巴巴開源的Admin框架,長這樣(還行吧,目前挺主流的): 官網地址:[https://pro.ant.design/index-cn](https://pro.ant.design/

004-ant design pro安裝、目錄結構、項目加載啟動

assets ocs win 領域 org 參考 des 布局 class 一、概述 1.1、腳手架概念   編程領域中的“腳手架(Scaffolding)”指的是能夠快速搭建項目“骨架”的一類工具。例如大多數的React

002-ant design pro 布局

篩選 html imp 我們 mas app 路由 http span 一、概述   參看地址:https://pro.ant.design/docs/layout-cn   其實在上述地址ant-design上已經有詳細介紹,本文知識簡述概要。   頁面整體布局是一

003-ant design pro 路由和菜單

部分 doc angle line board 面包屑 腳手架 封裝 ebp 一、概述   參看地址:https://pro.ant.design/docs/router-and-nav-cn 二、原文摘要   路由和菜單是組織起一個應用的關鍵骨架,我們的腳手架提供了

006-ant design pro 樣式

module text patch 導致 multipl 應該 back wid round 一、概述   參看地址:https://pro.ant.design/docs/style-cn   基礎的 CSS 知識或查閱屬性,可以參考 MDN文檔。 二、詳細介紹

010-ant design pro advanced 圖表

mage water 分享 rtc 分享圖片 cit nod 繪制 wave 一、概述 原文地址:https://pro.ant.design/docs/graph-cn Ant Design Pro 提供了由設計師精心設計抽象的圖表類型,是在 BizCharts 圖表