<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
上一章我們已經完成/docs
目錄下檔案自動生路由功能,本章我們將在此基礎上,實現自動生成頁面導航的功能。
在我們建立預設umi
專案後,會在/src/layouts
下生成一個佈局檔案:
同時在上一章節我們列印modifyRoutes
hook的入參,可以看到umi
會將該檔案轉成一個layout router物件,如圖所示:
因此我們可以直接將這個layout的id
屬性,賦值到自動生成的路由的parentId
屬性上,並新增該物件到返回值中:
// /src/features/routes.ts import path from 'path'; import type { IApi } from 'umi'; import type { IRoute } from '@umijs/core/dist/types'; import { getConventionRoutes } from '@umijs/core'; export default (api: IApi) => { api.describe({ key: 'domi:routes' }); api.modifyRoutes((oRoutes: Record<string, IRoute>) => { const routes: Record<string, IRoute> = {} const docDir = 'docs' // 獲取某個目錄下所有可以設定成umi約定路由的檔案 const dirRoutes: Record<string, IRoute> = getConventionRoutes({ base: path.join(api.cwd, docDir), }); // 預設提供的佈局layout的Id let docLayoutId : undefined | string = '@@/global-layout'; // 從舊路由物件中獲取放入返回值中 routes[docLayoutId] = oRoutes[docLayoutId] Object.entries(dirRoutes).forEach(([key, route]) => { // 這裡將檔案的路徑改為絕對路徑,否則umi會預設找/src/pages下元件 route.file = path.resolve(docDir, route.file); // 給頁面物件賦值佈局Id route.parentId = docLayoutId routes[route.id] = route; }); return routes; }); };
同時我們修改佈局檔案,將導航改成我們的測試頁面路由:
// /src/layouts/index.tsx import { Link, Outlet } from 'umi'; import styles from './index.less'; export default function Layout() { return ( <div className={styles.navs}> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/button">Button</Link></li> </ul> <Outlet /> </div> ); }
執行專案可以看到佈局檔案已新增到頁面中,並可以切換路由:
上面我們通過最簡單的方式使用了預設提供的佈局檔案,這種方式對頁面侷限性比較大,由於各個專案對頁面的展示要求不一樣,dumi
提供了主題外掛來靈活擴充套件使用者自定義佈局。同時提供了預設主題,使用者可以選擇性覆蓋預設樣式。
本節我們將實現其中的預設主題載入
建立主題外掛,並註冊到外掛設定中
mkdir /src/features/theme.ts
import { defineConfig } from "umi"; export default defineConfig({ plugins: [ './src/features/routes.ts', './src/features/theme.ts', ], });
建立預設主題目錄,將/src/layouts/index.tsx
檔案複製到這裡
mkdir /src/client/theme-default/layouts/DocLayout cp /src/layouts/index.tsx /src/client/theme-default/layouts/DocLayout/index.tsx cp /src/layouts/index.less /src/client/theme-default/layouts/DocLayout/index.less
然後/src/layouts
就沒用了,可以刪掉
dumi
主題外掛主要提供的功能有:
本章我們將實現預設佈局的載入,並設定到路由中。
umi
提供modifyAppData
勾點,用於初始收集應用資料,在dumi
中使用這個勾點來初始化主題資料。
我們在主題外掛中提供的主題資料後續會被用在修改路由中,即在modifyRoutes
階段使用。因為modifyRoutes
是在appData
外掛的modifyAppData
階段中執行,所以通過before: 'appData
讓主題外掛的modifyAppData
在appData
外掛的modifyAppData
之前先初始化完成,這樣在modifyRoutes
中就可以使用到主題資料。
// /src/features/theme.ts import path from 'path'; import type { IApi } from 'umi'; import { glob, winPath } from 'umi/plugin-utils'; const DEFAULT_THEME_PATH = path.join(__dirname, '../../src/client/theme-default'); export default async(api: IApi) => { api.describe({ key: 'domi:theme' }); api.modifyAppData({ before: 'appData', async fn(memo: any) { const defaultThemeData = loadTheme(DEFAULT_THEME_PATH); // @ts-ignore api.service.themeData = defaultThemeData return memo; }, }); } /** * 載入主題資訊 */ function loadTheme(dir: string) { return { name: path.basename(dir), path: dir, layouts: getComponentMapFromDir( 'layouts/{GlobalLayout,DocLayout,DemoLayout}{.,/index.}{js,jsx,ts,tsx}', dir, ), }; }; /** * 提取dir目錄下符合條件的元件資訊 */ function getComponentMapFromDir(globExp: string, dir: string) { return glob .sync(globExp, { cwd: dir }) .reduce<any>((ret, file) => { const specifier = path.basename( winPath(file).replace(/(/index)?.[a-z]+$/, ''), ); // ignore non-component files if (/^[A-Zd]/.test(specifier)) { ret[specifier] = { specifier, source: winPath(path.join(dir, file)), }; } return ret; }, {}); }
另一個比較不優雅的地方是這裡使用了api.service
來儲存生成的主題資料,同樣因為上面提到的階段問題,modifyRoutes
是在modifyAppData
中執行,所以這裡只能用全域性變數來儲存,否則在修改路由階段拿不到這裡的資料。
執行完成後,api.service.themeData
就得到了主題相關的資料:
{ name: 'theme-default', path: 'D:\project\domi\src\client\theme-default', layouts: { DocLayout: { specifier: 'DocLayout', source: 'D:/project/domi/src/client/theme-default/layouts/DocLayout/index.tsx' } } }
前面我們使用了模板自帶的物件@@/global-layout
作為佈局模板,現在我們可以將它改成動態新增主題佈局。
我們直接在路由外掛中使用主題外掛中生成的佈局資料,程式碼很簡單,根據前面的layout來生成一個佈局路由,並新增到返回值中即可,這樣所有parentId
為DocLayout.specifier
的頁面就能使用該佈局了。
// /src/features/routes.ts ... let docLayoutId : undefined | string = undefined; // @ts-ignore const { DocLayout } = api.service.themeData.layouts; // 從舊路由物件中獲取放入返回值中 if (DocLayout) { docLayoutId = DocLayout.specifier; routes[DocLayout.specifier] = { id: DocLayout.specifier, path: '/', file: DocLayout.source, parentId: undefined, absPath: '/', isLayout: true, }; } ...
// /umi/packages/core/src/service/service.ts 中程式碼 service.collectAppData() { // /src/features/theme.ts中程式碼 // 設定before: 'appData' 使其先於appData.modifyAppData執行 themePlugin.modifyAppData() { // 這裡載入主題資料 api.service.themeData = loadTheme(DEFAULT_THEME_PATH); } // /umi/packages/preset-umi/src/features/appData/appData.ts 中程式碼 appDataPlugin.modifyAppData() { // /src/features/routes.ts中程式碼 routesPlugin.modifyRoutes() { // 這裡使用主題資料生成佈局路由 const { DocLayout } = api.service.themeData.layouts; routes[DocLayout.specifier] = { ... isLayout: true, }; } } }
至此我們已經完成生成預設佈局,實現了簡易的主題外掛,執行程式碼可以看到和上節執行結果一樣:
路由和頁面問題基本解決了,接下來就要開始正式解析markdown
檔案。
以上就是umi外掛開發仿dumi專案實現頁面佈局詳解的詳細內容,更多關於umi外掛仿dumi頁面佈局的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45