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

这是一个特色叉 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 结构之外,以便更好的性能。 这对复杂的标签内容特别有用,当布局模型改变时,这些标签内容不应该重新回复.
主要惠益
- 对布局变化没有重新回复 - 当模型改变时,标签组件不重新提交
- 国家保全 - Tab 状态(滚动位置、窗体输入等)在整个布局变异中保留
- CSS 仅更新 - 只有CSS属性在布局变化时会改变,避免重现
如何运作
OptimizedLayout调制Layout轻量级TabRef占位符而不是实际标签内容TabRef组件从TabNode编号- 一个兄弟
TabContainer使实际标签内容具有绝对位置 - 在拖动操作中,
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 () |