@aptre/flex-layout

中文文档
0.6.4发布于 2026/04/21ISCTypeScriptES Module零依赖构建来源已验证近 30 天下载 2.2万

多塔布局管理器

中文使用文档
文档目录19 节
  1. 演示
  2. 安装
  3. 使用量
  4. 示例配置 :
  5. 示例代码
  6. 优化 版式
  7. 主要惠益
  8. 如何运作
  9. 示例使用
  10. 道具
  11. 何时使用优化Layout
  12. JSON模型结构
  13. 示范行动
  14. 实例
  15. 可选版式道具
  16. JSON 示范定义
  17. 创建新标签的布局组件方法
  18. 标签节点事件
  19. 替代布局管理器

FlexLayout (英语)

npm Build status GitHub Website

FlexLayout是支持多个 TabSets 的布局管理器,带有可拖动+重力标签.

FlexLayout Demo Screenshot

这是一个特色叉 FlexLayout (英语) 由卡普林执导. 最初的项目在一段时间内没有更新过,因此这个分叉包括了bug修正,性能改进等新功能 OptimizedLayout。 。 。 .

npm install @aptre/flex-layout
yarn add @aptre/flex-layout
pnpm add @aptre/flex-layout
bun add @aptre/flex-layout

FlexLayout唯一的依赖是反应.

特征 :

  • 分隔符
  • 选项卡
  • 选项卡拖放和顺序
  • 选项卡集拖放( 在一个操作中移动标签集中的所有标签)
  • 连接到标签集或边框
  • 最大化标签集(双击标签集头或使用图标)
  • 选项卡溢出( 标签溢出时显示菜单, 使用鼠标转盘滚动标签)
  • 边框标签集
  • 选项卡重命名( 双击标签文本重命名)
  • 主题 - 轻、下划线、灰色、圆和暗
  • 移动设备(iPad、Android)
  • 使用拖动添加标签, 添加到活动标签集, 添加到由 id 设置的标签
  • 选项卡和标签集属性:启用TabStrip,启用Dock,启用Drop...
  • 可自定义标签和标签集渲染
  • 移动标签时保留组件状态
  • 类型声明
  • 优化 版式 - 将标签内容置于FlexLayout的DOM之外,以提高性能

演示

尝试交互式演示 fleexlayout. 空间波.app。 。 。 .

API 文档可见于 fleexlayout.spacewave.app/typedoc/ 互联网档案馆的存檔,存档日期2013-12-02。 。 。 .

要在本地运行测试,克隆这个repo,然后:

bun install
bun run test:browser

安装

FlexLayout在 npm 仓库中. 使用 :

npm install @aptre/flex-layout

在模块中导入 FlexLayout :

import {Layout, Model} from '@aptre/flex-layout';

包含光线、下划线、灰色或暗色主题:

添加额外导入 :

import '@aptre/flex-layout/style/light.css';

或将 cs 添加到您的 html 中:

<link rel="stylesheet" href="node_modules/@aptre/flex-layout/style/light.css" />

使用量

这个 <Layout> 组件使制表器和分页器具有下列道具:

所需的道具 :

Prop说明
模式布局模式
工厂用于创建 React 组件的工厂函数

额外 可选道具

模型是定义布局结构的节点对象树.

工厂是一个函数,它取出一个节点对象并返回一个反应组件,该组件应该由布局中的标签来托管.

模型可以使用Model. from Json(json Object)静态方法创建,也可以使用model.toJson()方法保存.

示例配置 :

var json = {
    global: {},
    borders: [],
    layout: {
        type: "row",
        weight: 100,
        children: [
            {
                type: "tabset",
                weight: 50,
                children: [
                    {
                        type: "tab",
                        name: "One",
                        component: "button",
                    },
                ],
            },
            {
                type: "tabset",
                weight: 50,
                children: [
                    {
                        type: "tab",
                        name: "Two",
                        component: "button",
                    },
                ],
            },
        ],
    },
};

示例代码

const model = Model.fromJson(json);

function App() {
    const factory = (node) => {
        var component = node.getComponent();

        if (component === "button") {
            return <button>{node.getName()}</button>;
        }
    };

    return <Layout model={model} factory={factory} />;
}

上述代码将使两个制表符横向各包含一个主机按钮组件的单个制表符. 标签可以通过拖放来移动并调整大小. 通过向模型发送动作,可以在布局上添加额外的网格.

优化 版式

OptimizedLayout 是一个包裹周围 Layout 将标签内容置于 FlexLayout 的 DOM 结构之外,以便更好的性能。 这对复杂的标签内容特别有用,当布局模型改变时,这些标签内容不应该重新回复.

主要惠益

  1. 对布局变化没有重新回复 - 当模型改变时,标签组件不重新提交
  2. 国家保全 - Tab 状态(滚动位置、窗体输入等)在整个布局变异中保留
  3. CSS 仅更新 - 只有CSS属性在布局变化时会改变,避免重现

如何运作

  1. OptimizedLayout 调制 Layout 轻量级 TabRef 占位符而不是实际标签内容
  2. TabRef 组件从 TabNode编号
  3. 一个兄弟 TabContainer 使实际标签内容具有绝对位置
  4. 在拖动操作中, TabContainer 用途 pointer-events: none 防止干扰 FlexLayout 拖放

示例使用

import { Model, OptimizedLayout } from "@aptre/flex-layout";
import "@aptre/flex-layout/style/light.css";

const json = {
    global: {},
    borders: [],
    layout: {
        type: "row",
        weight: 100,
        children: [
            {
                type: "tabset",
                weight: 50,
                children: [{ type: "tab", name: "Editor", component: "editor" }],
            },
            {
                type: "tabset",
                weight: 50,
                children: [{ type: "tab", name: "Preview", component: "preview" }],
            },
        ],
    },
};

const model = Model.fromJson(json);

function App() {
    // renderTab receives a TabNode and returns the content for that tab
    const renderTab = (node) => {
        const component = node.getComponent();

        if (component === "editor") {
            return <Editor />;
        }
        if (component === "preview") {
            return <Preview />;
        }
        return <div>Unknown component: {component}</div>;
    };

    return (
        <div style={{ position: "relative", width: "100%", height: "100vh" }}>
            <OptimizedLayout model={model} renderTab={renderTab} />
        </div>
    );
}

道具

OptimizedLayout 接受所有与 Layout,但:

  • renderTab (需要) - 替换 factory函数 TabNode 并返回反应元素,以制成标签内容.

所有其他 Layout 道具( r)model, (中文(简体) ), onModelChange, (中文(简体) ), classNameMapper) 工作方式相同.

何时使用优化Layout

使用 OptimizedLayout 当:

  • 您的标签内容很昂贵
  • 您需要在整个布局变化中保留内部组件状态
  • 您有很多标签, 想要最小化重接

使用标准 Layout 当:

  • 当模型改变时, 您需要重新提交标签内容
  • 您的标签内容简单而轻巧
  • 你需要工厂模式来装入懒惰的部件

JSON模型结构

模型json包含3个顶级元素:

  • 全球 - (可选) 定义全球选项
  • 布局 - 主行/tabset/tabs布局等级
  • 边框 - (可选) 最多定义了 4 个边框 ("上","下","左","右")

使用3个“ 节点” 类型来构建布局元素 :

  • 行 - 行包含一个标签集和子行列表,顶级的"行"将水平渲染(除非设置了全局属性根OrientationVertical) ,孩子的"rows"将会在相反的方向向父母行.

  • 选项卡集 - 选项卡集包含一个标签列表和所选标签索引

  • 选项卡 - 选项卡指定它们应该主机的组件名称(这些组件将通过工厂加载)和实际选项卡的文本.

版式结构由行内包含自有标签的标签集来定义.

可选边界元素由边界节点组成

  • 边框 - 边框包含标签列表和所选标签的索引,它们只能用于边框 顶级元素.

JSON 模型的树结构被很好的定义为 Typescription 接口,参见 JSON 模型

每类节点都有一组定义的要求/可选属性.

行和制表盘上的重量指定了这些节点在母行内的相对权重,实际值并不仅仅关系它们的相对值(一是两个制表盘的重量为30,70,如果它们有3,7的权重,它们就会产生同样的效果.

通过改变全局或节点属性,可以改变布局外观和功能,例如:

在全局选项中设置标签SetEnableTabStrip:false会将布局改变为多分配器( 没有) 选项卡或拖放.

 global: {tabSetEnableTabStrip:false},

示范行动

模型json被装入后,模型中的所有修改都会通过动作应用.

您使用 Model.doAction() 方法.

此方法使用单个参数, 由一个动作创建 发电机(通常以 FlexLayout.Actions.<actionName>) (中文(简体) ).

见 动作.ts 用于可用的行动.

实例

model.doAction(
    FlexLayout.Actions.updateModelAttributes({
        splitterSize: 40,
    }),
);

上面的例子会增加拆分器的大小,可以用来制作 调整小设备上的布局更方便.

model.doAction(FlexLayout.Actions.addNode({ type: "tab", component: "grid", name: "a grid", id: "5" }, "1", FlexLayout.DockLocation.CENTER, 0));

此示例在标签集中心以 id "1" 为单位添加了新的网格组件,并在 0't tab 位置上添加了新的网格组件(使用值 - 1来添加到标签的结尾).

注:您可以得到节点的ID(例如,节点由节点返回) addNode 动作)使用方法 node.getId()。 。 。 . 如果在节点创建时没有指定一个代号,那么一个代号将会以形式为您创建 #<uuid> (例如:. #0c459064-8dee-444e-8636-eb9ab910fb27) (中文(简体) ).

注意: 您可以在应用 GUI 更改前先截取操作 执行 onAction 调用属性 Layout。 。 。 .

可选版式道具

在布局上可以应用许多可选属性. 见 在布局.tsx 中的 ILayoutProps 用于完整的接口.

JSON 示范定义

JSON模型被很好地定义为一组TypeScript接口. 见 IJsonModel.ts (英语) 用于所有可用属性:

  • IJsonModel - 顶级模型结构
  • IGlobalAttributes - 全球配置属性
  • IJsonRowNode - 行配置属性
  • IJsonTabSetNode - 标签集配置属性(注意:标签集在移动标签时是动态创建的,在空出时被删除,除非 enableDeleteWhenEmpty 错误)
  • IJsonTabNode - 标签配置属性
  • IJsonBorderNode - 边界配置属性

创建新标签的布局组件方法

布局组件中有添加标签的方法 。 见 版式.tsx 用于现有方法.

示例

layoutRef.current.addTabToTabSet("NAVIGATION", {type:"tab", component:"grid", name:"a grid"});

这将在带有 id “ NAVIGATION” 的标签集中添加一个新的网格组件( 其中版式参考文件是对版式元素的回溯, 参见 https://react.dev/learn/reference-values- with-refs 互联网档案馆的存檔,存档日期2013-12-02 ) (中文(简体) ).

标签节点事件

您可以在节点上通过添加一个收听器处理事件, 通常这样做 当组件以使用效果方法挂起时:

示例

    function MyComponent({node}) {

      useEffect(() => {
        // save subject in flexlayout node tree
        node.setEventListener("save", () => {
             node.getConfig().subject = subject;
           };
        }, []);
    }

活动参数说明
调整大小[ rect] (英语)当标签在布局时调整大小时调用, 调用后, 才会用新大小渲染
关闭无关闭标签时调用
可见度{可看见}当标签的能见度改变时调用
保存无在标签节点被序列化为json之前调用, 用于通过将数据添加到由节点返回的对象中来保存节点配置 。 getConfig ()

替代布局管理器

名称仓库
弧-多克https://github.com/ticlo/rc-dock (中文(简体) )
挂起视图https://dockview.dev/ (英语)
发光https://github.com/jupyterlab/lumino 页面存档备份,存于互联网档案馆
黄金铺出https://github.com/golden-layout/golden-layout 页面存档备份,存于互联网档案馆
反应-发作https://github.com/nomcopter/react-mosaic 互联网档案馆的存檔,存档日期2013-12-21

版本与发布记录

@aptre/flex-layout 共发布 49 个版本,首次发布于 2023/10/19;过去 12 个月发布了 22 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.6.4latest2026/04/216 个月前
0.6.32026/04/166 个月前
0.6.22026/02/118 个月前
0.6.12026/02/118 个月前
0.6.02026/02/118 个月前
0.5.132026/02/118 个月前

其他发布通道:beta → 0.3.0-beta.5。

关于 @aptre/flex-layout 的常见问题

@aptre/flex-layout 是什么?

多塔布局管理器

如何安装 @aptre/flex-layout?

在项目目录运行 npm install @aptre/flex-layout,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(^19.2.5)、react-dom(^19.2.5)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@aptre/flex-layout 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@aptre/flex-layout 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@aptre/flex-layout 可以商用吗?

@aptre/flex-layout 使用 ISC 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@aptre/flex-layout 的下载量有多少?

根据 npm 官方下载统计,@aptre/flex-layout 在 2026/10/07 – 2026/11/05 这 30 天内被下载 21,931 次,日均约 731 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aptre/flex-layout 还在维护吗?

最新版本 0.6.4 发布于 2026/04/21(6 个月前);至今共发布 49 个版本,其中过去 12 个月发布了 22 个;首次发布于 2023/10/19。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。