指南

自定义节点内容

「#default 插槽 / node-component / render-content」三种自定义节点内容的写法与优先级

三种等价写法,优先级:#default 插槽 > node-component > render-content。三者都缺省时渲染节点的 label。

节点自定义内容

可自行设置节点内容。

写法:
xxx科技有有限公司
这是一个有活力的公司
产品研发部
这是一个有活力的产品研发部
研发-前端
这是一个有活力的研发-前端
研发-后端
这是一个有活力的研发-后端
UI 设计
这是一个有活力的UI 设计
销售部
这是一个有活力的销售部
销售一部
这是一个有活力的销售一部
销售二部
这是一个有活力的销售二部
财务部
这是一个有活力的财务部
三种等价写法:render-content(与原版一致)、node-component(Vue 3 版新增,传一个以 { node, data } 为 props 的组件)、#default 作用域插槽。优先级:插槽 > node-component > render-content。render-content 签名为 (h, node): h 是 Vue 的渲染函数,node 是内部 Node 实例(源数据在 node.data,还可读取 node.isCurrent、 node.expanded 等状态)。也可以改用作用域插槽 #default="{ node, data }"。
<template>
  <vue-okr-tree
    :data="testData"
    direction="horizontal"
    show-collapsable
    default-expand-all
    :render-content="renderContent"
  />

  <!-- 等价的 node-component 写法:传组件,props 为 { node, data } -->
  <vue-okr-tree :data="testData" direction="horizontal" :node-component="DiyCard" />

  <!-- 等价的插槽写法 -->
  <vue-okr-tree :data="testData" direction="horizontal">
    <template #default="{ node, data }">
      <div class="diy-wrapper">
        <div class="diy-con-name">{{ data.label }}</div>
        <div class="diy-con-content">{{ data.content }}</div>
      </div>
    </template>
  </vue-okr-tree>
</template>

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

const testData = ref([{
  label: 'xxx科技有有限公司', content: '这是一个有活力的公司',
  children: [{
    label: '产品研发部', content: '这是一个有活力的产品研发部',
    children: [
      { label: '研发-前端', content: '这是一个有活力的研发-前端' },
      { label: '研发-后端', content: '这是一个有活力的研发-后端' },
      { label: 'UI 设计', content: '这是一个有活力的UI 设计' }
    ]
  }, {
    label: '销售部', content: '这是一个有活力的销售部',
    children: [
      { label: '销售一部', content: '这是一个有活力的销售一部' },
      { label: '销售二部', content: '这是一个有活力的销售二部' }
    ]
  }, {
    label: '财务部', content: '这是一个有活力的财务部'
  }]
}])

// h 由组件传入;node 为内部 Node 实例
function renderContent(h, node) {
  return h('div', { class: ['diy-wrapper', node.isCurrent ? 'current-select' : ''] }, [
    h('div', { class: 'diy-con-name' }, node.data.label),
    h('div', { class: 'diy-con-content' }, node.data.content),
  ])
}
</script>

<style>
.diy-wrapper { display: flex; flex-direction: column; align-items: flex-start; }
.diy-wrapper .diy-con-name { font-size: 12px; line-height: 18px; color: #646a73; }
.diy-wrapper .diy-con-content { color: #1f2329; line-height: 22px; font-size: 14px; }
.diy-wrapper.current-select .diy-con-name { color: red; }
.diy-wrapper.current-select .diy-con-content { color: #1989fa; }
</style>
显示代码

render-content

签名 (h, node):h 是 Vue 的渲染函数(由组件从 vue 导入后传入),node 是内部 Node 实例(源数据在 node.data,文本在 node.label,另有 isCurrent / expanded / leftExpanded / isLeftChild / level / childNodes 等)。这与 element-ui 的 (h, { data }) 不同,与 vue-okr-tree 保持一致。

renderContent.ts
function renderContent(h, node) {
  return h('div', { class: ['diy', node.isCurrent && 'is-current', node.isLeftChild && 'left'] }, [
    h('div', node.data.label),
    h('small', node.data.content),
  ])
}

node-btn-content 用同一套参数约定,定制展开按钮内容。

node-component

传一个组件,以 { node, data } 为 props 渲染(Vue 3 版新增):

App.vue
<vue-okr-tree :data="data" :node-component="DeptCard" />

#default 插槽

作用域插槽(Vue 3 版新增,原版的插槽实际不可用):

App.vue
<vue-okr-tree :data="data">
  <template #default="{ node, data }">
    <b>{{ data.label }}</b>
    <small v-if="node.isCurrent">(已选中)</small>
  </template>
</vue-okr-tree>

其余插槽

插槽名说明作用域参数
expand-btn展开按钮内容;show-node-num 开启时折叠态的数字优先于该插槽{ node, data, expanded, side, loading },side 为 right(常规/右子树)或 left(OKR 左子树),loading 为懒加载进行中
emptydata 为空数组时在容器内渲染—

类型收窄

需要插槽作用域里的 data 带上自己的数据类型,用 createTypedOkrTree<T>()。

Copyright © 2026