:新增、關閉頁簽與 onEdit 回調機制)
ant-design Tabs 可編輯卡片頁簽實戰(zhàn)新增、關閉頁簽與 onEdit 回調機制【免費下載鏈接】ant-designAn enterprise-class UI design language and React UI library項目地址: https://gitcode.com/gh_mirrors/antde/ant-design本文基于 ant-design 倉庫中 新增和關閉頁簽示例 展開講清楚typeeditable-card頁簽的完整實現(xiàn)方式如何用受控狀態(tài)管理頁簽列表panes、如何用onEdit(targetKey, action)回調處理新增與關閉操作、關閉當前頁簽后如何回退激活態(tài)。讀完本文你能掌握一套可直接復制運行的可編輯頁簽方案并能從 Tabs 組件源碼 層面理解關閉圖標與加號入口是如何被注入到頁簽欄中的。一、適用前提只有卡片樣式支持新增與關閉示例文檔開頭就給出了一條關鍵約束只有卡片樣式的頁簽支持新增和關閉選項。這是由 Tabs 組件源碼 直接決定的。在AntTabs的render方法中只有當type editable-card時組件才會對每個子頁簽做克隆、注入關閉按鈕并向 tab bar 右側追加新建頁簽的加號圖標components/tabs/index.jsx#L42-L59。默認的type值為line見defaultPropscomponents/tabs/index.jsx#L79-L85線條樣式頁簽不具備該能力。因此啟用新增/關閉功能的第一條件就是設置typeeditable-card??ㄆ瑯邮奖旧碓?卡片式頁簽示例 中有單獨演示typecard只提供不可關閉的卡片外觀而editable-card是其增強形態(tài)。二、完整可運行示例受控 panes onEdit以下是倉庫示例 editable-card.md 的完整代碼核心思路是頁簽列表本身也是受控狀態(tài)import { Tabs } from antd; const TabPane Tabs.TabPane; const Demo React.createClass({ getInitialState() { this.newTabIndex 0; const panes [ TabPane tab選項卡 key1選項卡一內容/TabPane, TabPane tab選項卡 key2選項卡二內容/TabPane, ]; return { activeKey: panes[0].key, panes, }; }, onChange(activeKey) { this.setState({ activeKey }); }, onEdit(targetKey, action) { thisaction; }, add() { const panes this.state.panes; const activeKey newTab${this.newTabIndex}; panes.push(TabPane tab新建頁簽 key{activeKey}新頁面/TabPane); this.setState({ panes, activeKey }); }, remove(targetKey) { let activeKey this.state.activeKey; let lastIndex; this.state.panes.forEach((pane, i) { if (pane.key targetKey) { lastIndex i - 1; } }); const panes this.state.panes.filter(pane pane.key ! targetKey); if (lastIndex 0 activeKey targetKey) { activeKey panes[lastIndex].key; } this.setState({ panes, activeKey }); }, render() { return ( Tabs onChange{this.onChange} activeKey{this.state.activeKey} typeeditable-card onEdit{this.onEdit} {this.state.panes} /Tabs ); } }); ReactDOM.render(Demo /, mountNode);需要注意的環(huán)境前提該倉庫快照為 antd 0.12.x 早期版本見 package.json 中version: 0.12.17react: 0.14.x示例使用React.createClass寫法底層頁簽由rc-tabs ~5.8.0實現(xiàn)。這套panes 數(shù)組 受控 activeKey的狀態(tài)管理模式與后續(xù)版本的 API 是兼容的遷移到函數(shù)組件時只需把thisaction這類實例方法換成函數(shù)即可。關鍵點 1panes 數(shù)組是頁簽的唯一數(shù)據(jù)源panes在getInitialState中初始化每個TabPane必須有唯一keyactiveKey與panes[0].key對齊保證初始激活第一個頁簽渲染時通過{this.state.panes}把整個數(shù)組交給Tabs增刪頁簽都只需setState更新數(shù)組React 會完成 diff。關鍵點 2onEdit 用 action 做動態(tài)分發(fā)onEdit(targetKey, action)的兩個參數(shù)由組件內部回調提供add()生成newTab${n}形式的自增 keypush一個新頁簽并同步把activeKey切到新頁簽實現(xiàn)新增后自動激活remove()先用filter移除目標頁簽再處理激活態(tài)回退。thisaction這種把回調的actionadd/remove當方法名調用的寫法是示例中最簡潔的分發(fā)技巧。關鍵點 3關閉當前激活頁簽時的激活態(tài)回退remove()里最容易踩坑的是激活態(tài)處理if (lastIndex 0 activeKey targetKey) { activeKey panes[lastIndex].key; }邏輯是先記錄被刪頁簽的下標lastIndex i - 1即它的前一個頁簽位置過濾出新數(shù)組后再判斷——如果刪掉的恰好是當前激活頁簽就把激活態(tài)切到新數(shù)組中同下標位置的頁簽也就是被刪頁簽的左鄰。兩個邊界條件都做了保護lastIndex 0刪除的是第一個頁簽時不存在左鄰保持當前激活態(tài)不變此時activeKey指向一個已不存在的 key由上層業(yè)務兜底或可進一步改為回退到panes[0].keyactiveKey targetKey只有被刪頁簽正是激活頁簽時才需要切換。三、源碼解析AntTabs 如何包裝 rc-tabs 注入編輯能力Tabs 組件源碼 整體是對rc-tabs的薄封裝import Tabs from rc-tabsAntTabs類只額外做了四件事1. 把 rc-tabs 的事件映射為 onEdit 協(xié)議createNewTab(targetKey) { this.props.onEdit(targetKey, add); } removeTab(targetKey, e) { e.stopPropagation(); if (!targetKey) { return; } this.props.onEdit(targetKey, remove); }components/tabs/index.jsx#L15-L24組件對外只暴露一個onEdit(targetKey, action)回調action取值固定為add或remove這正是示例中onEdit(targetKey, action)參數(shù)的來源。removeTab中的e.stopPropagation()防止點關閉圖標時同時觸發(fā)頁簽切換!targetKey的判空則防御了點擊加號區(qū)域等沒有目標 key 的情況。2. 為每個子頁簽克隆注入關閉圖標if (type editable-card) { children children.map((child, index) { return cloneElement(child, { tab: div {child.props.tab} Icon typecross onClick{this.removeTab.bind(this, child.key)} / /div, key: child.key || index, }); }); // Add new tab handler tabBarExtraContent ( span Icon typeplus className{${prefixCls}-new-tab} onClick{this.createNewTab} / {tabBarExtraContent} /span ); }components/tabs/index.jsx#L41-L59實現(xiàn)要點用cloneElement重寫每個TabPane的tab屬性在原標簽文字后追加一個Icon typecross關閉圖標onClick通過bind(this, child.key)預綁定頁簽 key若子元素缺少key則回退用數(shù)組下標index兜底key: child.key || index這也是為什么實踐中仍強烈建議顯式給每個TabPane設置key加號入口是通過重寫tabBarExtraContent實現(xiàn)的——把用戶傳入的附加內容包進一個span前面加上Icon typeplus classNameant-tabs-new-tab。這意味著tabBarExtraContent與加號可以共存加號總是排在附加內容之前。Icon是 antd 內部的 iconfont 組件components/icon/index.jsx只渲染一個帶anticon anticon-{type}類名的i元素所以關閉圖標和加號最終都是字體圖標視覺細節(jié)由 Less 控制。3. 類名與動畫策略render中的類名拼裝components/tabs/index.jsx#L29-L40與示例行為直接相關type.indexOf(card) 0時附加ant-tabs-card類同時生成ant-tabs-${type}類即ant-tabs-editable-card樣式層正是靠這兩個類名定位卡片/可編輯樣式當tabPosition為left/right或類型為卡片時強制animation null關閉頁簽切換動畫——從源碼結構看可編輯卡片頁簽不支持垂直方向布局也不做內容滑入滑出動畫tabBarExtraContent最終統(tǒng)一包進ant-tabs-extra-content容器components/tabs/index.jsx#L61-L65對應樣式中float: right的右側區(qū)域。四、樣式層關閉圖標與加號的視覺細節(jié)style/components/tabs.less 中ant-tabs-editable-card相關的樣式解釋了頁簽欄的交互觀感卡片外觀style/components/tabs.less#L387-L415卡片式頁簽容器高 36px隱藏了線條樣式的ant-tabs-ink-bar指示條visibility: hidden每個頁簽改為淺灰背景 頂部圓角border-radius: 6px 6px 0 0的方塊激活頁簽切換為白底、主題色文字和可見邊框。關閉圖標的漸進式顯示style/components/tabs.less#L419-L444非激活且未懸停的頁簽中anticon-cross的width: 0且overflow: hidden即關閉圖標默認收起不占寬度頁簽激活或 hover 時-tab-active .anticon-cross或-tab:hover .anticon-cross寬度展開到 16px配合transform形成平滑的出現(xiàn)動畫非激活頁簽 hover 時ant-tabs-editable-card還會把-tab-inner的左右內邊距從 16px 收縮到 8pxstyle/components/tabs.less#L435-L438為展開的關閉圖標騰出空間避免文字跳動。新建頁簽加號style/components/tabs.less#L446-L466ant-tabs-new-tab被渲染成 20x20 的圓角方框帶 1px 邊框、12px 字號默認灰色#999、hover 加深為#404040位于ant-tabs-extra-content區(qū)域內靠右浮動。五、相關 API 速查editable-card 場景結合 組件文檔 中的 API 表在可編輯頁簽場景中真正用得到的參數(shù)如下參數(shù)說明類型默認值type頁簽樣式必須為editable-card才能啟用新增/關閉另有l(wèi)ine、cardStringlineonEdit新增和刪除頁簽的回調僅在typeeditable-card時有效Function(targetKey, action)無activeKey當前激活 tab 面板的 key示例中用它做完全受控String無defaultActiveKey初始化選中面板的 key未設置activeKey時使用String第一個面板onChange切換面板的回調示例中用它同步activeKeyFunction無onTabClicktab 被點擊的回調Function無tabBarExtraContenttab bar 上額外的元素editable-card下加號圖標會自動排在其前面React Node無size大小提供default和small兩種StringdefaulttabPosition頁簽位置toprightbottomleft卡片/可編輯樣式下垂直位置會關閉內容動畫StringtopTabPane側只有兩個屬性key對應activeKey與tab頁簽頭顯示文字React.Element 或 String。對于editable-cardkey實際上是必需的——它是onEdit回調中targetKey的唯一來源也是cloneElement注入關閉圖標時綁定的目標。六、進階用法提示基于源碼的注入機制見第三節(jié)有兩個進階點可以直接利用附加內容共存tabBarExtraContent與加號不沖突可參照 附加內容示例 傳入操作按鈕源碼保證加號在附加內容左側渲染。例如在新建頁簽加號旁放一個批量導入按鈕是文件管理類產(chǎn)品常見的頁簽欄布局完全受控示例同時使用了activeKey而非defaultActiveKey與onChange回寫狀態(tài)這是頁簽列表可變場景下的推薦姿勢——頁簽數(shù)組隨時在變激活態(tài)必須由自己維護否則刪除/新增后激活態(tài)可能指向不存在的 key。Tabs 組件通過 index.js 中的Tabs: require(./components/tabs)統(tǒng)一導出導入方式即import { Tabs } from antd。整套panes 數(shù)組 onEdit 分發(fā) 激活態(tài)回退的模式是 ant-design 早期版本中實現(xiàn)文件頁簽、多文檔編輯等可關閉標簽頁交互的標準做法?!久赓M下載鏈接】ant-designAn enterprise-class UI design language and React UI library項目地址: https://gitcode.com/gh_mirrors/antde/ant-design創(chuàng)作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考