指南

复选框与拖拽

复选框联动与半选语义、拖拽三分区放置判定与 allow-drag / allow-drop 钩子

两块 1.9.0 / 1.10.0 加入的交互能力,语义都对齐 el-tree 的使用习惯。

复选框选择

App.vue
<vue-okr-tree :data="data" node-key="id" show-checkbox default-checked-keys="[3]" />

复选框选择模式(show-checkbox)

节点前渲染复选框,父子联动半选态;可切换 check-strictly 关闭联动。

事件输出(最近 8 条)
尚未触发事件,试试点击节点 / 右键 / 展开按钮
设置 show-checkbox 开启复选框;父子联动半选态,check-strictly 可关闭联动。check 回调参数为 (data, { checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys });check-change 在每个状态变化的节点上触发,参数为 (data, checked, indeterminate)。方法 getCheckedKeys / setCheckedKeys / getHalfCheckedKeys / isChecked 通过 ref 调用。OKR 模式下左右两树勾选独立维护,方法按 key 对两树同时生效。
<template>
  <vue-okr-tree
    ref="treeRef"
    :data="testData"
    direction="horizontal"
    show-collapsable
    show-checkbox
    node-key="id"
    :default-checked-keys="[3, 4]"
    @check="handleCheck"
    @check-change="handleCheckChange"
  />
</template>

<script setup>
import { ref } from 'vue'
import { VueOkrTree } from 'vue3-okr-tree'

const treeRef = ref()
const testData = ref([{ id: 1, label: 'xxx科技有有限公司', children: [/* … */] }])

function handleCheck(data, { checkedKeys, halfCheckedKeys }) {
  console.log(checkedKeys, halfCheckedKeys)
}
function handleCheckChange(data, checked, indeterminate) {
  console.log(data.label, checked, indeterminate)
}
// 通过 ref 调用方法
// treeRef.value.setCheckedKeys([7, 8])
// treeRef.value.getCheckedKeys() / getHalfCheckedKeys() / isChecked(key)
</script>
显示代码

联动规则:

  • 勾选父节点向下联动全部后代(含 disabled 节点——disabled 只阻止直接点击),祖先按子树重算全选 / 半选。「全部子节点选中 ⇒ 父选中」,所以唯一子链选中会让父节点直接变全选。
  • check-strictly 关闭联动,勾选只作用于自身;运行时切换后新交互按新模式执行。
  • default-checked-keys 需配 node-key,创建期生效;运行时内容变更会先清空再按新列表应用(宿主只是换了个等值数组引用时不重放,不会把用户改过的勾选抹回去),data 重建后不恢复(与 default-expanded-keys 一致)。
  • OKR 模式下左右两树的勾选独立维护(点击只作用于所在树),而 setCheckedKeys / getCheckedKeys 等按 key 对两树同时生效 / 合并去重。
  • 勾选态在增删子节点、懒加载 resolve、data 增量重建后自动重算祖先。

事件与方法:check 只在点击复选框时触发(携带全量勾选信息),check-change 在每个状态变化的节点各触发一次(联动、setCheckedKeys 批量、增删级联都覆盖)。方法为 getCheckedKeys / getCheckedNodes / setCheckedKeys / getHalfCheckedKeys / getHalfCheckedNodes / isChecked。键盘 Space 切换勾选、Enter 选中;treeitem 输出 aria-checked,半选为 mixed(见键盘导航)。

样式复用既有变量(边框取 --okr-line-color、填充取 --okr-current-bg),六套主题与自定义主题零配置适配。

拖拽调整层级

App.vue
<vue-okr-tree :data="data" node-key="id" draggable :allow-drop="allowDrop" @node-drop="onDrop" />

拖拽调整层级(draggable)

拖动节点卡片,放到目标节点的上 / 内 / 下三个区域完成移动(水平模式按纵向分区)。

事件输出(最近 8 条)
尚未触发事件,试试点击节点 / 右键 / 展开按钮
设置 draggable 开启拖拽,移动会同步修改源数据 children; 放置位置对齐 el-tree:prev(目标前 25%)/ inner(中间,成为子节点并自动展开)/ next(后 25%),指示线颜色可用 --okr-drop-color 定制。硬性规则:不可放到自身或自己的子树内; allow-drag(node) 可禁止拖动(本例禁止拖「财务部」), allow-drop(dragging, target, type) 可按位置过滤;OKR 模式跨左右树默认禁止, allow-drop 返回 true 可放开。
<template>
  <vue-okr-tree
    ref="treeRef"
    :data="testData"
    direction="horizontal"
    show-collapsable
    draggable
    node-key="id"
    :allow-drag="allowDrag"
    :allow-drop="allowDrop"
    @node-drag-start="onDragStart"
    @node-drop="onDrop"
  />
</template>

<script setup>
import { ref } from 'vue'
import { VueOkrTree } from 'vue3-okr-tree'

const treeRef = ref()
const testData = ref([{ id: 1, label: 'xxx科技有有限公司', children: [/* … */] }])

const allowDrag = (node) => node.key !== 9
const allowDrop = (dragging, target, type) => type !== 'inner'
function onDrop(dragging, target, type) {
  console.log(dragging.label, target.label, type)
}
// 编程式移动(同样同步源数据):
// treeRef.value.moveNode(12, 11, 'inner')
</script>
显示代码
  • 放置分区为 25% / 50% / 25%,并按布局方向换轴:horizontal(同级上下排列)按 Y 轴 prev 上 / inner 中 / next 下;vertical(同级左右排列)按 X 轴 prev 左 / inner 中 / next 右。指示线画在节点卡片上(prev / next 指示线、inner 虚线描边),颜色用 --okr-drop-color 定制。
  • 移动同步修改源数据的 children(与 append / remove 同一套语义,冻结数据下跳过写入并警告,见需要注意的行为),并修正整棵子树的 level 与节点注册表;inner 放置时目标自动展开。
  • 硬性规则:不可拖到自身或自己的子树内(allow-drop 越不过这条),disabled 节点不可拖。
  • OKR 模式跨左右树默认禁止;allow-drop 明确返回 true 才放开,放开后整棵子树的 isLeftChild 标记与左右注册表随之迁移。
  • 六个事件:node-drag-start(node, event)、node-drag-enter / leave / over(draggingNode, dropNode, event)、node-drag-end(draggingNode, dropNode | null, dropType | null, event)、node-drop(draggingNode, dropNode, dropType, event)。未完成放置时 node-drop 不触发、node-drag-end 的后两参为 null。
  • 不用鼠标也能改层级:moveNode(data, target, type) 与拖拽走同一条 moveNode 路径,data / target 均接受 key、data 对象或 Node 实例。

相关页面

Copyright © 2026