基于React+Antd的多Tab架构

12,390 阅读2分钟

背景

企业后台布局常采用多tab的方式,即可通过不同tab之间的切换访问已打开的页面,如下图所示。后台管理系统中一种常见的场景为从列表页到详情页展示,多tab的形式能够更好的满足这种业务场景,尤其在不同的tab页有对比的情况下。

多tab

实现方案

使用react-router的方式实现

我们可以通过每个标签记录不同的路由的形式,即<tab, url>键值对的形式,记录该标签对应的路由,点击不同的标签时,在Content区域渲染相关的路由对应的组件来实现多tab。

但是这种方案有一个问题无法绕开,那就是react-router是根据url来渲染单个组件的,无法缓存已渲染的组件,这就意味着在点击标签时,对应的子组件每次都是重新渲染,无法保存上次对应的状态(React-router原理)。这对于纯展示类的场景影响在可接受范围内,如标签对应的是新闻详情页,即使刷新也无大碍。但对于某种场景则存在很大的问题,如输入型场景中,我在标签1中输入了部分内容,之后切换到标签2中去查询某个数据,再回到标签1中,刚才输入的数据项则丢失。

如果React-router可以缓存组件,便可解决这个问题。通过查询react-router文档发现并不支持,react中也没有像vue中keep-alive的机制。业界中有react-keeper的路由方案代替react-router解决组件的缓存问题。

基于JQuery的方式实现

在React没出现之前,在JQ中如何实现这种形式的呢?用JQ的方式是比较容易实现的,只需要将标签对应的内容的css设置为{display: block},其他标签对应的内容css设置为{display: none}即可。

基于Antd Tab组件实现

Antd tab组件实现了上述所说的JQ类似的功能,示例如下:

import {Tabs, Button} from 'antd';
const {TabPane} = Tabs;
ReactDOM.render( <
    <Tabs activeKey="1" >
        <TabPane tab = "Tab 1" key = "1" >Content of tab 1 </TabPane> 
        <TabPane tab = "Tab 2" key = "2" >Content of tab 2 </TabPane> 
        <TabPane tab = "Tab 3" key = "3" >Content of tab 3 </TabPane> 
    </Tabs>,
    mountNode,
);

activeKey对应的TabPane会呈现,其他TabPane则会隐藏掉。

首先设计Tab的数据结构:

{
    name,  // 该标签名称
    component, // 标签对应的组件
    props, // 组件需要的属性
}

在全局状态中增加:

// 全局标签列表
{
    tabs: [] // 全局tabs
}

// 对应的操作
export const ADD_TAB = 'ADD_TAB';
export const REMOVE_TAB = 'REMOVE_TAB';
export const UPDATE_TAB = 'UPDATE_TAB';
export const CHANGE_TAB = 'CHANGE_TAB';
export const CLEAR_TAB = 'CLEAR_TAB';

标签的新增,关闭,更新等对应的就是tabs数组的以上操作。

代码如下:github.com/simonwoo/mu…

效果如下图:

效果图