Files
aurora-admin/site/end-content/enhancedtabnav.react.json
T

99 lines
6.2 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"slug": "enhancedtabnav",
"end": "react",
"curated": true,
"summary": "可拖拽页签栏:不接收任何 props,页签数据、拖拽排序与右键菜单全部是组件内部状态。",
"usage": [
"React 端这个组件没有 props——函数签名就是无参数的 EnhancedTabNav(),页签来自模块内的 INITIAL 常量(EnhancedTabNav.jsx:4-12)。",
"拖拽排序用原生 HTML5 拖放:页签上设 draggable=\"true\" 与 data-id,onDragStart 记 id、容器 onDrop 里读 dataset.id 重排(EnhancedTabNav.jsx:77-80,55-68)。",
"右键菜单是自绘的:onContextMenu 阻止默认菜单后,在 clientX/clientY 处渲染三项菜单(关闭/关闭其他/关闭全部)(EnhancedTabNav.jsx:40-44,91-95)。",
"关闭逻辑带保底:只剩一个页签时不做删除,关闭当前项后自动激活它左边的一项(EnhancedTabNav.jsx:30-38)。",
"未保存标记是数据字段 dirty,为真时在标题前渲染一个圆点(EnhancedTabNav.jsx:5-8,83)。",
"点击外部收起菜单靠 document 级 click 监听,在 useEffect 清理函数里解绑(EnhancedTabNav.jsx:20-26)。"
],
"bestPractices": [
"要接入真实业务必须先改这份组件:它把演示数据与状态写死在内部,没有 items/onChange 之类的出口(EnhancedTabNav.jsx:13-17)。",
"onDrop 用 e.target.closest 找页签,因此页签内部的子元素(圆点、×)也能正确落到同一行目标上(EnhancedTabNav.jsx:56)。",
"拖拽只在同一容器内排序,没有跨容器或跨窗口能力。"
],
"apiCarrier": {
"kind": "props",
"note": "React 端的 API 载体是 props 与回调:属性驱动外观(type/size/disabled 等布尔与枚举),交互经 onXxx 回传(如 onChange/onClick/onSelectionChange);没有 v-model,受控组件固定写成 value + onChange,非受控则用 defaultValue。",
"table": [
{
"name": "tabs",
"type": "INITIAL 常量(内部 state)",
"desc": "页签数组,由内部 setTabs 维护,组件不接收它作为 prop"
},
{
"name": "activeId",
"type": "string",
"desc": "当前激活页签 id,内部 state(默认 u),组件不接收它作为 prop"
},
{
"name": "draggable",
"type": "\"true\"",
"desc": "页签节点上的原生拖放开关(DOM 属性,非组件 props)"
},
{
"name": "data-id",
"type": "string",
"desc": "页签 DOM 上的 id 数据属性,onDrop 靠它定位(DOM 属性,非组件 props)"
},
{
"name": "onDragStart",
"type": "() => void",
"desc": "页签上的内部处理器,拖起时记录 dragId(非组件 props)"
},
{
"name": "onDrop",
"type": "(e) => void",
"desc": "容器上的内部处理器,落到页签上时按 data-id 重排 tabs(非组件 props)"
},
{
"name": "onContextMenu",
"type": "(e, id) => void",
"desc": "页签上的内部处理器,右键时记录坐标与目标 id 并打开菜单(非组件 props)"
},
{
"name": "onClick",
"type": "() => void",
"desc": "页签上的内部处理器,点击切换到该 id(非组件 props)"
}
]
},
"a11y": [
"页签是带 onClick 的 div(EnhancedTabNav.jsx:74-82),没有 role=\"tab\"/aria-selected,读屏不知当前激活项。",
"拖拽排序只能用鼠标,键盘无法移动页签位置;右键菜单同样没有键盘入口(无 Shift+F10/菜单键处理)。",
"关闭标记是带 onClick 的 span 且已 stopPropagation(EnhancedTabNav.jsx:85),但它不可聚焦,键盘用户无法关闭页签;底部提示文案是纯文本说明(EnhancedTabNav.jsx:97)。"
],
"resources": [
{
"file": "frameworks/EnhancedTabNav.jsx",
"kind": "React(React)",
"desc": "React 端组件实现源码,props 与回调的唯一定义处"
},
{
"file": "frameworks/EnhancedTabNav.css",
"kind": "样式",
"desc": "该 React 实现依赖的样式文件"
}
],
"exampleIds": [
"enhancedtabnav-ex-1"
],
"notes": [
"frameworks/EnhancedTabNav.jsx:13 中可指到 tabs(INITIAL 常量(内部 state))——页签数组,由内部 setTabs 维护,组件不接收它作为 prop",
"frameworks/EnhancedTabNav.jsx:14 中可指到 activeId(string)——当前激活页签 id,内部 state(默认 u),组件不接收它作为 prop",
"frameworks/EnhancedTabNav.jsx:77 中可指到 draggable(\"true\")——页签节点上的原生拖放开关(DOM 属性,非组件 props)",
"frameworks/EnhancedTabNav.jsx:78 中可指到 data-id(string)——页签 DOM 上的 id 数据属性,onDrop 靠它定位(DOM 属性,非组件 props)",
"frameworks/EnhancedTabNav.jsx:80 中可指到 onDragStart(() => void)——页签上的内部处理器,拖起时记录 dragId(非组件 props)",
"frameworks/EnhancedTabNav.jsx:55 中可指到 onDrop((e) => void)——容器上的内部处理器,落到页签上时按 data-id 重排 tabs(非组件 props)",
"frameworks/EnhancedTabNav.jsx:72 中可指到 onContextMenu((e, id) => void)——页签上的内部处理器,右键时记录坐标与目标 id 并打开菜单(非组件 props)",
"frameworks/EnhancedTabNav.jsx:79 中可指到 onClick(() => void)——页签上的内部处理器,点击切换到该 id(非组件 props)",
"props 解构清单见 frameworks/EnhancedTabNav.jsx:12-12;本文件 table 只列该端真正消费的属性与回调。",
"过滤口径:事实包 consumedApi 里还包含绑在组件内部节点上的同名处理器(如 onClick/onChange 绑在内部 button、input、checkbox 上,见 frameworks/EnhancedTabNav.jsx 全文),它们不是对外 props,因此未进 table。",
"table 构成核验:8 行中 0 行是 frameworks/EnhancedTabNav.jsx 解构出的顶层 props(解构块 frameworks/EnhancedTabNav.jsx:12-12);另 8 行不是顶层 props,而是 frameworks/EnhancedTabNav.jsx 内部 state 或 items[*] 数据字段,desc 已逐行标明其来源(组件不接收这些名字作为 prop)。"
]
}