Capabilities
组件能做的事,全部写进 API 表
以下每一条都对应一个真实 prop 或方法,与 vue3-okr-tree 的运行时行为逐项核对过。
三种布局形态
direction 切垂直 / 水平,onlyBothTree 让子树在根节点左右两侧展开,左树是同一组件的完整镜像。
OKR 根对齐
alignRoot 用纯 CSS 固定根节点水平坐标,展开收起不再跳位;OkrTreeGroup 让多棵树的左栏取最宽者对齐。
六套主题与 --okr-* 变量
default / feishu / dark / auto / minimal / colorful 内置,全部外观由 --okr-* 变量推导,自定义主题只需自写一个类。
六种展开动画
animateName 提供 fade 与 zoom 四向共 6 组过渡,时长可调;系统开启「减弱动态效果」时自动按关闭处理。
CSS 与 SVG 双连接线
默认伪元素画线,connector="svg" 换成覆盖层路径且布局零改动,三种形状随展开收起自动重绘。
勾选、拖拽与懒加载
复选框带父子联动与半选态,HTML5 拖拽换父级含 prev / inner / next 三区校验,lazy 首次展开时取数。
受控与非受控双模
expandedKeys / currentKey 成对 props 即受控,不传即非受控;ref 上的方法接受 key、data、TreeNode 三种入参。
Layouts
三种布局,一个组件
下面每一块都是真实渲染的 OkrTree,差别只有 props。几何(节点间距、连线端点、层叠顺序)由同一套 CSS 变量驱动。
垂直(direction="vertical")
默认形态:自上而下分层,子节点在父节点下方居中排布。
水平(direction="horizontal")
组织架构图常用形态:同层节点竖排成一列,向右生长。
OKR 双树(onlyBothTree + alignRoot)
飞书 OKR 形态:leftData 在根节点左侧展开,右树同组件同 API,左树是完整镜像。
connector="svg"(curve)
连接线换成覆盖层路径,布局零改动;展开收起时经突变订阅重绘,另有 orthogonal 与 straight 两种形状。
unstyled
只保留结构与布局,卡片外观与连线全部中和——需要完全自绘样式时的起点,打印样式也走这条路。
六套内置主题
主题只是根容器上的一个 okr-theme-* 类,全部取值来自 --okr-* 变量; 自写一个类即可接入第 7 套。注意组件主题与站点明暗是两回事。
default(原版外观)
feishu
dark
auto(跟随系统)
minimal
colorful(按层级着色)
现在就把它放进你的 React 项目
零运行时依赖,peer 只要求 React 18.2 以上。样式是一条独立的style.css,不引就只是个纯结构树。
$ npm i react-okr-tree@1.13.0FAQ
装之前大概会问的
React 版本要求是多少?
peer 是 react / react-dom >= 18.2.0,React 19 也在范围内。 之所以不停在 19:18.2 起 useSyncExternalStore 与并发渲染已经齐备,再抬高等级只会白丢用户。 本仓库的 peer 矩阵作业会额外用 React 18.2 + @types/react@18 编一份消费者示例,确保产出的 d.ts 不引用 React 19 独有类型。
支持 SSR / 静态导出吗?
支持。渲染路径上不碰 window / document,浏览器专属能力(ResizeObserver、滚轮监听、字体就绪测量) 全部放在 effect 里;订阅层给 useSyncExternalStore 备了常量 getServerSnapshot,所以服务端不会 hydration 报警。 一个约束:受控初始值(expandedKeys / currentKey)在 store 创建期就写入,首屏 HTML 即最终状态。
和 vue3-okr-tree 是什么关系?
同一套功能的 React 移植,属性 / 事件 / 方法逐项对齐,连原版的拼写错误也原样保留(showCollapsable、currentLableClassName),这样两端可以共用一份功能核对清单。 差异集中在机制层面:kebab-case → camelCase、事件 → onXxx 回调、插槽 → render props、v-model:x → x + onXxxChange。 完整对照见 迁移说明。
我直接改了 data 里的对象,树为什么没更新?
React 没有 Vue 那套深监听。data 换了引用一定会重建;同引用原地 push / splice 则靠组件渲染时的结构脏检查接住——前提是宿主确实重渲染了。 如果是第三方状态库改的数据而组件没重渲染,显式调用 ref.refreshData() 兜底。另外增删类方法会回写你传入的源数据(与源项目一致),冻结对象上这类回写会静默跳过并给一次开发期警告。
包有多大?会不会带进一堆依赖?
零运行时依赖:react / react-dom 是 peer,html-to-image 只是 optional peer(只有 exportImage 用到,走变量化的动态 import,不装也不会被打进包)。 CSS 单独一条 react-okr-tree/style.css,不引样式就是纯结构。 体积门禁写在 package.json 的 size-limit 段,CI 每次都量。
键盘可用吗?暗色怎么给?
role=tree / treeitem / group 齐备,漫游 tabindex 全局唯一, 方向键与 Home / End 沿可见节点移动,OKR 模式下左右树之间用 ← / → 跨接; 系统开了「减弱动态效果」时,展开动画与平滑滚动自动按关闭处理。 外观是 theme prop(6 套内置)加 --okr-* 变量覆盖,auto 跟随系统,也可以完全自绘(unstyled)。