背景
企业后台布局常采用多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数组的以上操作。
效果如下图: