最近我写了一个你用任何UI框架就能自己组装的界面标签页管理器,实现效果如下图

项目地址
简单介绍下如何使用
以下仅用vue作为示例
如何定义数据
在npm install @meogic/tab-manager-vue --save后创建对应的数据模型,比如
export class UserTabNode extends TabNode<Component> {
static getType(): string {
return 'user-tab';
}
private __user: User;
static clone(node: UserTabNode): UserTabNode {
const tabNode = new UserTabNode(node.__user, node.__active, node.__key)
return tabNode;
}
constructor(user:User, active?: boolean, key?: NodeKey) {
super(user.name, active, key);
this.__user = user
}
//region getters
getUser(): User {
const self = this.getLatest()
return self.__user
}
//endregion
//region mutations
setUser(value: User): this {
const self = this.getWritable()
self.__user = value
return this
}
//endregion
decorate(tabManager: TabManager, config: TabManagerConfig): Component {
return h(
UserDetail,
this.exportJSON()
);
}
static importJSON<T>(serializedNode: SerializedUserTabNode): UserTabNode {
const node = $createUserTabNode(serializedNode.user, serializedNode.active);
return node;
}
exportJSON(): SerializedUserTabNode {
return {
name: this.getName(),
active: this.getActive(),
user: this.getUser(),
type: 'tab',
version: 1,
};
}
}
export function $createUserTabNode(user: User, active?: boolean) {
return new UserTabNode(user, active)
}
这里名为
$createUserTabNode的函数,$开头是标识其只能在update回调函数中使用
如何定义页面结构
创建好了对应的数据后,接下来就是搭建页面
<TabManagerComposer :initial-config="config" @error="onError">
<TabManagerRootElement/>
<TabGroupBarPlugin/>
<Decorators/>
<TabGroupResizablePlugin/>
<TabGroupDraggablePlugin/>
</TabManagerComposer>
- 这里的
TabManagerRootElement是你整个标签页管理器的根DOM对象 TabManagerComposer则是给整个子组件提供tabManager对象的上下文- 这里的config的用途除了可以指定对应主题要用到的css类名,以及注册的Node类等功能外,还可以设置初始化状态,比如
function prepared() {
const root = $getRoot();
const window = $createWindowNode()
const tabGroupNode = $createResizableTabGroupNode()
tabGroupNode.setActive(true)
tabGroupNode.setPercent(33.33)
const tabGroupBar = $createTabGroupBarNode()
tabGroupNode.append(tabGroupBar)
const tabGroupNode2 = $createResizableTabGroupNode()
tabGroupNode2.setPercent(33.33)
const tabGroupBar2 = $createTabGroupBarNode()
tabGroupNode2.append(tabGroupBar2)
const tabGroupNode3 = $createResizableTabGroupNode()
tabGroupNode3.setPercent(33.33)
const tabGroupBar3 = $createTabGroupBarNode()
tabGroupNode3.append(tabGroupBar3)
root.append(
window.append(
tabGroupNode,
tabGroupNode2,
tabGroupNode3
)
)
}
const config = {
tabManagerState: prepared,
namespace: 'Playground',
nodes: [...PlaygroundNodes],
tabNodes: [UserTabNode],
tabGroupNodes: [ResizableTabGroupNode],
theme
}
基础的交互
可以看到这里并没有用到上面定义的UserTabNode,那是因为添加Tab需要触发一系列操作
tabManager.update(() => {
const tabGroupNode = $getNodeByKey(tabGroupNodeKey)
if(!$isTabGroupNode(tabGroupNode)){
return
}
const userTabNode = $createUserTabNode(user)
tabGroupNode.append(userTabNode)
$updateTabGroupBarNode(tabGroupNode)
$activeTabNode(userTabNode)
})
TabManagerOpenPlugin.vue 比如我们在点击了用户列表页里的一个项目时,需要在Tab中打开时
- 找到当前正在激活的
tabGroupNode - 将对应的
userTabNodeappend 到tabGroupNode下 - 同时通过
$updateTabGroupBarNode更新这个tabGroupNode对应的tabGroupBar,使其新增对应的标签页头部 - 最后通过
$activeTabNode在激活当前新增的tabNode,同时隐藏其它的tabNode
直接本地试用
上面基本演示了如何定义数据、如何定义页面结构、以及基础的交互,可能你觉得还是有点懵,没关系,项目代码中已经有示例了。
git clone git@github.com:meogic-tech/meogic-tab-manager.git
npm i --force
npm run dev
然后你就能在lcoalhost上看到了
最后
由于时间与精力的限制,我只提供了vue的示例与工具库,如果你喜欢本项目且愿意贡献代码的话,欢迎你的PR。最后如果本项目对你有所帮助,请帮我点一个star,谢谢!