craft.js 0.1.x 迁移指南:多选(Multiselect)机制下的 EditorState 与节点规则升级
前端【免费下载链接】craft.js A React Framework for building extensible drag and drop page editors项目地址https://gitcode.com/gh_mirrors/cr/craft.js点击查看免费下载导读本文以 craft.js 官方迁移文档 site/docs/migrating/0.1.x.md 为主体系统梳理从 0.1.x 升级到 0.2.x 时由多选Multiselect功能引发的三处破坏性变更EditorState.events从单值NodeId变为集合SetNodeId、基于useEditor的状态收集方式需要改用.has()判断、User Component 的canMoveIn/canMoveOut规则参数从单个Node变为Node[]。阅读本文后你将能够准确识别旧代码中的迁移点并掌握与新事件模型及数组化规则签名对应的完整改造写法。背景为什么 0.2.x 引入了破坏性变更0.1.x 时代的 EditorState 一次只能表达一个“事件目标”当前被选中的节点、被拖拽的节点或被悬停的节点各自都只是一个NodeId。从 0.2.x 开始craft.js 引入了Multiselect多选能力允许用户同时框选多个节点并在一次拖拽中批量移动多个节点。多选使得事件模型必须从“单数”变成“复数”——同一个selected/dragged/hovered事件不再指向唯一节点。这一能力直接体现在核心包的类型定义中EditorEvents被定义为RecordNodeEventTypes, SetNodeIdpackages/core/src/interfaces/editor.ts事件类型仅有三种selected | dragged | hoveredpackages/core/src/interfaces/nodes.tsEditorState通过events: EditorEvents字段挂载这一集合模型packages/core/src/interfaces/editor.ts。因此凡是读取state.events的旧代码都必须同步升级否则类型检查与运行时行为都会出错。变更一EditorState.events 从 NodeId 变为 Set官方迁移文档给出了最直观的类型差异// 0.1.x type EditorState { ... // same as before events: NodeId; } // 0.2.x type EditorState { ... // same as before events: SetNodeId; }对应到当前仓库的源码实现这一签名不仅停留在类型层也贯穿了运行时状态更新逻辑。在 packages/core/src/editor/actions.ts 的setNodeEvent中可以看到先把state.events[eventType]中所有旧节点的事件标记清空state.nodes[id].events[eventType] false将state.events[eventType]重置为new Set()通过getNodesFromSelector解析目标节点支持idOnly/existOnly选项把解析出的 id 列表构造成SetNodeId后写回state.events[eventType]。也就是说events字段在 0.2.x 中始终是Set而不是数组或单个 id。仓库中的测试也验证了这一行为packages/core/src/editor/tests/actions.test.ts 用actions.setNodeEvent(selected, [node-a, node-b])同时选中两个节点并断言期望状态为events: { selected: new Set([node-a, node-b]) }。此外clearEvents()现在会一次性清空三类事件selected、hovered、dragged并重置放置指示器packages/core/src/editor/actions.ts这与集合模型的整体替换语义保持一致。升级要点小结维度0.1.x0.2.xstate.events.selectedNodeId字符串SetNodeId判断某节点是否被选中 node-id.has(node-id)多节点事件表达不支持一个Set同时容纳多个节点 id底层更新方式单值覆盖new Set()整体重建后写入变更二更新 useEditor 收集的状态值由于events变成了Set所有通过useEditor的 collector 函数从state.events收集值的代码都必须从等值比较改为has判断。官方迁移文档给出的对照如下// 0.1.x const { selected, hovered, dragged } useEditor(state ({ selected: state.events.selected some-node-id, hovered: state.events.hovered some-node-id, dragged: state.events.dragged some-node-id, })) // 0.2.x const { selected, hovered, dragged } useEditor(state ({ selected: state.events.selected.has(some-node-id), hovered: state.events.hovered.has(some-node-id), dragged: state.events.dragged.has(some-node-id) }))从源码结构看useEditor的 collector 机制没有变化它接受一个可选的 collector 函数EditorCollectorS内部通过useInternalEditor订阅 store把收集到的切片值作为返回值暴露给组件packages/core/src/hooks/useEditor.tsx。因此迁移成本完全集中在“读取events的方式”上useEditor本身的调用形态、返回的actions/query对象均无需调整。实操检查清单搜索代码中所有state.events.selected 、state.events.hovered 、state.events.dragged 形式的等值比较一律改为state.events.selected.has(...)等.has()调用若某个事件值被当作字符串使用如直接传给 action、拼进 key 等需要重新审视语义0.2.x 下事件值可能是多个节点的集合。变更三canMoveIn / canMoveOut 规则签名升级为 Node[]多选不仅影响状态读取还影响 User Component 的移动规则。在 0.2.x 中canMoveIn与canMoveOut的第一个参数从单个Node变为Node[]因为一次拖拽可能携带多个传入/移出的节点规则必须能对“整批”节点做判断。官方迁移文档给出的对照示例const Button () { return (...) } // 0.1.x Button.craft { rules: { canMoveIn: (incomingNode: Node, currentNode: Node, helpers: NodeHelpers) { return incomingNode.data.name Text; }, canMoveOut: (outgoingNode: Node, currentNode: Node, helpers: NodeHelpers) { return outgoingNode.data.name Text; } } } // 0.2.x Button.craft { rules: { canMoveIn: (incomingNodes: Node[], currentNode: Node, helpers: NodeHelpers) { return incomingNodes.every(incomingNode incomingNode.data.name Text) }, canMoveOut: (outgoingNodes: Node[], currentNOde: Node, helpers: NodeHelpers) { return outgoingNodes.every(outgoingNode outgoingNode.data.name Text) } } }当前仓库的NodeRules类型定义与此完全一致——数组是必选签名export type NodeRules { canDrag(node: Node, helpers: NodeHelpersType): boolean; canDrop(dropTarget: Node, self: Node, helpers: NodeHelpersType): boolean; canMoveIn(canMoveIn: Node[], self: Node, helpers: NodeHelpersType): boolean; canMoveOut(canMoveOut: Node[], self: Node, helpers: NodeHelpersType): boolean; };见 packages/core/src/interfaces/nodes.ts其中NodeHelpersType QueryCallbacksFortypeof QueryMethods[node]即查询方法的 node 维度集合packages/core/src/interfaces/nodes.ts。另外需要注意Button.craft.rules属于可选的PartialNodeRulespackages/core/src/interfaces/nodes.ts并非所有规则都必须实现但一旦实现canMoveIn/canMoveOut就必须使用数组签名。数组参数在底层如何被使用从源码调用链看canMoveIn的数组参数在拖放校验isDroppable中扮演关键角色。在 packages/core/src/editor/NodeHelpers.ts 中isDroppable(selector, onError?)会先把selector解析为一批目标节点newParentNode.rules.canMoveIn( targets.map((selector) selector.node), newParentNode, nodeHelpers )即targets.map(selector selector.node)得到的Node[]会原样传入canMoveIn这意味着若规则仅判断“单个节点是否符合条件”请使用.every()全部满足才放行或按需使用.some()任一满足即可放行多选拖拽时一次isDroppable校验会针对整批节点触发一次canMoveIn而不是逐个触发返回值仍为booleaninvariant会在返回false时抛出ERROR_MOVE_INCOMING_PARENT之类的错误并阻止放置。迁移操作建议先跑类型检查升级到 0.2.x 后先对使用state.events和rules的代码执行 TypeScript 编译编译器会直接标出所有NodeId/Node与SetNodeId/Node[]不兼容的位置这比手工搜索更可靠。集中替换事件读取将useEditor及其他访问state.events的 collector 统一改为.has()判断并注意selected/hovered/dragged三类事件都要覆盖。重写移动规则把canMoveIn/canMoveOut的单节点参数改为数组参数并用every/some表达“整批放行”或“存在即放行”的策略多选拖拽下建议先用every保持与旧行为一致的严格校验。验证多选交互迁移完成后通过actions.setNodeEvent或直接框选多个节点确认state.events.selected为包含多个 id 的Set且拖拽多个节点时canMoveIn收到的是完整的Node[]可参考 packages/core/src/editor/tests/actions.test.ts 的断言写法编写自己的单元测试。小结0.2.x 的多选能力是本次迁移的根本动因它把事件模型从“单节点”提升为“节点集合”相应地带来两处接口级变更events字段与canMoveIn/canMoveOut签名和一处调用级变更collector 改用.has()。按照本文给出的三张对照表与检查清单即可在不改变组件结构的前提下完成平滑迁移并充分使用多选拖拽带来的批量编辑能力。赞分享前端【免费下载链接】craft.js A React Framework for building extensible drag and drop page editors项目地址https://gitcode.com/gh_mirrors/cr/craft.js点击查看免费下载相关推荐VoltAgent 迁移指南从 0.1.x 到 1.x 再到 2.x 的完整升级路径与源码级解析VoltAgent 迁移指南从 0.1.x 到 1.x 再到 2.x 的完整升级路径与源码级解析 本文基于 VoltAgent 仓库中的官方迁移文档 migr人工智能AI AgentAgent 框架后端多智能体RAG工具调用Agent 记忆Agent 工作流AI 评测MCP 服务MCP Clients语音Semantica 跨会话记忆实战用 save() 与 load() 让 Agent 重启不失忆的完整指南Semantica 跨会话记忆实战用 save 与 load 让 Agent 重启不失忆的完整指南 多数 AI Agent 的上下文都活在进程内存里一重启人工智能大模型知识图谱RAGAI 可解释性后端MCP 服务3步解锁数据自由WeChatMsg让你的聊天记录真正属于你3步解锁数据自由WeChatMsg让你的聊天记录真正属于你 你是否曾有过这样的瞬间想找回三年前和好友的那段珍贵对话却发现微信的聊天记录早已消失无踪。那些深上一篇gh_mirrors/c4/c4项目持续部署自动发布与版本管理下一篇3步搞定Yuedu书源误删恢复回收站功能全解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

ClawHub UI Proof Runtime:基于 Crabbox 的远程全栈 UI 验证体系解析

ClawHub UI Proof Runtime:基于 Crabbox 的远程全栈 UI 验证体系解析

后端前端AI 技能AI 插件搜索引擎 【免费下载链接】clawhub Skill Plugin Registry for OpenClaw 项目地址: https://gitcode.com/gh_mirrors/mo/clawhub 点击查看 免费下载 导读:specs/ui-proof.md 定义了 ClawHub 的远程 proof:ui 验证运行时——一种…

2026/9/25 5:44:34 阅读更多 →
fast-colors 命名颜色识别:isColorNamed() 类型守卫函数实战指南

fast-colors 命名颜色识别:isColorNamed() 类型守卫函数实战指南

前端UI组件 【免费下载链接】fast The adaptive interface system for modern web experiences. 项目地址: https://gitcode.com/gh_mirrors/fa/fast 点击查看 免费下载 isColorNamed() 是 FAST 项目 microsoft/fast-colors 颜色工具库中用于判定一个颜色字符串是否…

2026/9/25 5:44:34 阅读更多 →
LinkedIn Ads 数据源:配置、认证与增量同步实战

LinkedIn Ads 数据源:配置、认证与增量同步实战

数据工程数据编排ETL任务调度批处理流处理数据集成后端 【免费下载链接】mage-ai 🧙 Build, run, and manage data pipelines for integrating and transforming data. 项目地址: https://gitcode.com/gh_mirrors/ma/mage-ai 点击查看 免费下载 LinkedI…

2026/9/25 5:44:33 阅读更多 →

最新新闻

Atlas 300V 24G NPU部署YOLO全攻略:从ONNX到OM的推理加速实践

Atlas 300V 24G NPU部署YOLO全攻略:从ONNX到OM的推理加速实践

如果你是被“atlas部署yolo”和“atlas 300v 24g是运算加速卡吗”这两个问题带进来的,我猜你大概率和我一样:手里已经有一套跑得不错的YOLO检测模型,下一步想找一个比通用GPU更省电、比树莓派更强、又能塞进标准机箱里的推理加速设备。过去一…

2026/9/25 9:46:46 阅读更多 →
Atlas 300V 24G推理加速卡部署YOLO完整实践:从产品定位到多路调优

Atlas 300V 24G推理加速卡部署YOLO完整实践:从产品定位到多路调优

后台隔三差五就有人拿着同一个问题来问我:“Atlas 300V 24G是不是运算加速卡?”问的人多了,我大概能猜到他们经历了什么——要么是看中了这张卡的高性价比,想拿来跑模型训练;要么是把它当成游戏显卡,插上之…

2026/9/25 9:46:46 阅读更多 →
cursor+MCP系列:用TaoToken统一Key接入12306-MCP车票查询工具

cursor+MCP系列:用TaoToken统一Key接入12306-MCP车票查询工具

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 9:46:46 阅读更多 →
计算机小白也必须要掌握的Codex入门到进阶系列:用CC Switch与TaoToken统一Key打通API KEY配置

计算机小白也必须要掌握的Codex入门到进阶系列:用CC Switch与TaoToken统一Key打通API KEY配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 9:46:45 阅读更多 →
CiLocks地理位置回传原理:get.php的GET参数数据全链路拆解

CiLocks地理位置回传原理:get.php的GET参数数据全链路拆解

CiLocks地理位置回传原理:get.php的GET参数数据全链路拆解 【免费下载链接】CiLocks Crack Interface lockscreen, Metasploit and More Android/IOS Hacking 项目地址: https://gitcode.com/GitHub_Trending/ci/CiLocks CiLocks 是一款 Android/iOS 渗透测试…

2026/9/25 9:45:45 阅读更多 →
AI编程工具上传.git目录争议:抓包验证与敏感信息防护指南

AI编程工具上传.git目录争议:抓包验证与敏感信息防护指南

1. 事件背景与核心争议拆解1.1 一个让开发者集体炸锅的传闻最近开发者圈子里讨论度最高的话题之一,就是有用户声称在抓包分析时发现 ZCode 这个 AI 编程工具疑似把工作区里的.git目录内容上传到了云端。消息一出,各种截图、聊天记录、分析帖满天飞&#…

2026/9/25 9:45:45 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →