Skip to content
TinyWisp edited this page Jan 22, 2023 · 41 revisions

主要特色

  • 支持复选框
  • 可异步加载
  • 拖放操作
  • 右键菜单
  • 按钮
  • 自定义外观

开始使用

npm

  npm install twtree --save

引入

  import TWTree from 'twtree'

示例

<template>
 <div id="app">
   <TWTree :tree="tree" ref="tree" class="tree" />
 </div>
</template>

<script>
import TWTree from 'twtree'

export default {
 name: 'App',
 components: {
   TWTree
 },
 data() {
   return {
     tree: [
       {
         id: 1,
         title: 'ROOT',
         hasChild: true,
         children: [
           {
             id: 2,
             title: 'child 1',
           },
           {
             id: 3,
             title: 'child 2',
             hasChild: true,
             children: [
               {
                 id: 4,
                 title: 'child 2-1'
               },
               {
                 id: 5,
                 title: 'child 2-2'
               },
               {
                 id: 6,
                 title: 'child 2-3'
               }
             ],
           },
           {
             id: 7,
             title: 'child 3'
           },
           {
             id: 8,
             title: 'child 4'
           }
         ]
       }
     ]
   }
 }
}
</script>

<style scoped>
.tree {
 width: 200px;
 height: 300px;
}
</style>

vue3

点击此处 查看对vue3的支持

属性

属性 类型 默认值 说明
tree Array [] 树的结点数据
defaultAttrs Object {} 结点默认属性
checkboxLinkage Boolean true 选中取消复选框时,是否对他的父结点或子结点进行联动操作
dragImageOffsetX String 20px 拖动结点时,缩略图相对于鼠标的水平位置偏移
dragImageOffsetY String 10px 拖动结点时,缩略图相对于鼠标的垂直位置偏移
enableDragNodeOut Boolean false 允许将结点拖到树的外面
enableDropExternalElement Boolean false 允许将树外部的元素拖拽到树上
enableTouchSupport Boolean false 允许触屏上用手指进行拖拽操作
dropToMove Boolean true 拖和放都在一棵树中的时候,默认此拖放操作为移动结点
treeId String 空串 在多棵树之前做拖拽操作时,用于识别拖动的结点来源于哪棵树 详情
animationDuration String 0.5s 动画效果的展示时间,为0则取消动画效果
autoReload Boolean true 监测tree属性的变化,如果有变化,则自动重新加载数据
multiSelect Boolean false 是否可多选
pressEnterToBlur Boolean true 在编辑标题时,按下回车键后,是否使输入框失去焦点
fnLoadData Function(node) null 加载数据的回调函数。返回结点数组,或者返回一个promise,该promise成功时的值为结点数组
fnIsDroppable Function(dragAndDrop) null 拖放操作时判断当前是否可放下拖动中的元素
fnBeforeDrag Function(node) null 开始拖动元素时调用,返回false则停止拖放操作,返回true则继续
fnBeforeCheck Function(node) null 点击选中复选框时调用,返回false则停止选中复选框,返回true则继续
fnBeforeUncheck Function(node) null 点击取消复选框时调用,返回false则停止取消复选框,返回true则继续
fnBeforeSelect Function(node) null 点击选中某个结点时调用,返回false则停止选中结点,返回true则继续
fnBeforeExpand Function(node) null 展开目录时调用,返回false则停止展开,返回true则继续
fnBeforeCollpase Function(node) null 折叠目录时调用,返回false则停止折叠,返回true则继续
fnBeforeContextMenu Function(node) null 展示右键菜单时调用,返回false则停止展示菜单,返回true则继续
fnBeforeDrop Function(dragAndDrop) null 用户拖动结点到某个合适的位置后放开鼠标按键时调用,返回false,则停止移动结点到此位置,返回true则继续
fnAfterCalculate Function(node) null 计算结点属性时调用。可用来自定义计算结点的属性。
fnCustomClasses Function(node) null 为结点增加自定义样式类。当此方法返回一个class名称数组时,会为结点增加相应的class

事件

事件 说明
rename (node, node.title, title) 修改结点标题
edit (node) 编辑结点标题
quitedit (node) 退出编辑结点编题
focus (node, event) 编辑结点标题时,输入框获得焦点
blur (node, event) 编辑结点标题时,输入框失去焦点
input (node, event) 编辑结点标题时,有文字输入
keydown (node, event) 编辑结点标题时,有按键按下
keyup (node, event) 编辑结点标题时,有按键释放
keypress (node, event) 编辑结点标题时,按键按下
deselect (node) 取消选择结点
select (node) 选中结点
expand (node) 展开一个目录结点
collapse (node) 折叠一个目录结点
click (node) 点击结点
create (node) 添加子结点
remove (node) 删除结点
move (node, fromParent, fromPos, toParent, toPos) 移动结点
checkboxstatechange (node, oldState, state) 复选框状态变化
check (node) 复选框选中
uncheck (node) 复选框取消
dragstart (dragAndDrop) 开始拖动
dragover (dragAndDrop) 拖放操作时,鼠标/手指在某个结点上移动
dragenter (dragAndDrop, node) 拖放操作时,鼠标/手指进入某个结点
dragleave (dragAndDrop, node) 拖放操作时,鼠标/手指离开某个结点
dragend (dragAndDrop) 结束拖放操作
dragentertree(dragAndDrop) 拖放操作时,鼠标/手指从树的外面移动到树的内部
dragleavetree(dragAndDrop) 拖放操作时,鼠标/手指从树的内部区域来到树的外面

2.0.0有几个事件名称发生变化
dragStart -> dragstart
dragOver -> dragover
dragEnter -> dragenter
dragLeave -> dragleave
dragEnd -> dragend
quitEdit -> quitedit
checkboxStateChange -> checkboxstatechange

方法

方法 说明
reload() 重新加载组件的tree属性中的数据
一般情况下,不推荐直接修改tree属性中的数据。
推荐调用create,remove,move,setTitle等方法修改数据
traverse(fnDoSomething) 遍历所有结点
getNestedTree() 获取树,以嵌套形式返回所有结点
getFlatTree() 获取树,返回一个包含所有结点的扁平数组
getById(id) 根据id获取结点
getSelected() 获取选中的结点
getSelectedOne() 获取选中的第一个结点
setAttr(node, key, val)
setAttr(node, key, subKey, val)
设置结点属性
getAttr(node, key)
getAttr(node, key, subKey)
获取结点属性
setTitle(node, title) 设置结点标题
edit(node) 使结点进入编辑模式
quitEdit(node) 使结点退出编缉模式
getTitleElement(node) 获取结点的DOM元素
focus(node) 编辑模式时,使输入框获得焦点
blur(node) 编辑模式时,使输入框失去焦点
getNewTitle(node) 编辑模式时,获取新标题
2.13.0后,node.title直接和输入框绑定。不再需要此方法。
deselect(node) 取消结点的选中状态
select(node) 选中结点
hideContextMenuOnDisplay() 隐藏正在显示的右键菜单
create(node, parentNode, pos)
create(node, parentNode)
为某结点添加子结点。
不传入pos参数时,将结点添加在末尾。
createAndEdit(node, parentNode, pos)
create(node, parentNode)
添加结点后并编辑该结点的标题,用法跟create一样。
remove(node) 删除结点
move(node, toParent, toPos)
move(node, toParent)
移动结点。
不传入toPos参数时,把结点放到末尾的位置。
search(keyword, fnMatch)
search(keyword)
搜索树,并返回符合条件的结点。 详情
sort(node, recursive, fnCompare)
sort(node, recursive)
排序。详情
clearSearchResult() 清除搜索结果
expand(node) 展开目录结点
expandAncestors(node) 展开某个结点的所有祖先结点
collapse(node) 折參目录结点
getNodeElement() 获取结点的DOM元素
getOffset(node) 获得结点的像素位置
setCheckboxState(node, state) 设置复选框状态
check(node) 选中复选框
uncheck(node) 取消复选框
toggleCheckbox(node) 选中或消取复选框
getChecked() 获取复选框为选中的结点
getUndetermined() 获取复选框状态不明确的目录结点
getUnchecked() 获取复选框未被选中的结点
toggleDirectoryState(node) 展开/折叠目录结点
isTheTouchOperationFromTheTree(event) 判断一个触屏操作是否是从某棵树上开始的
getDragFrom() 获取当前拖拽操作的来源
返回数据结构如 {treeId: 'leftTree', nodeId: 3}

结点属性

__.xxx属性由组件自动生成及维护,用户可以读取,但最好不要手动修改这些属性

属性 类型 默认值 说明
id mixed 唯一标识
title String 标题
hasChild Boolean false 是否有子结点
children Array [] 子结点
directoryState String expanded 目录结点状态。枚举值:expanded, collapsed, loading
selected Boolean false 是否处于选中状态
checkbox.show Boolean false 是否显示复选框
checkbox.disable Boolean false 是否禁用复选框
checkbox.state String unchecked 复选框状态。枚举值: checked, unchecked, undetermined
style.height String 2em 结点高度。如"2em"
style.indent String 20px 相对于父结点的缩进。如"20px"
style.fontSize String 12px 字符尺寸。如“12px”
style.hoverBgColor String #e7f4f9 鼠标移动经过该结点时的背景色
style.selectedBgColor String #e7f4f9 选中时的背景色
style.switcherMarginRight String 0.1em 为文件夹状态图标(折叠展开加载中)设置css的margin-right属性
style.iconMarginRight String 0.5em 为icon设置css的margin-right属性
style.checkboxMarginRight String 0.1em 为checkbox设置css的margin-right属性
style.extraFloatRight Boolean false 是否使插槽extra浮动到右端(设置css属性float:right)
style.extraAlwaysVisible Boolean false 是否使插槽extra的内容总是显示,而不仅仅是在鼠标滑过时显示
style.titleMaxWidth String none 为title设置最大宽度。详情
style.titleOverflow String clip 为title设置text-overflow属性。
如果希望标题超过宽度后显示省略号,设为ellipsis。
注意一下: css属性text-overflow可以自定义一些字符串,
但在这里有可能会出现浏览器兼容性问题。
style.showIcon Boolean true 是否显示图标
style.showSwitcher Boolean true 是否显示文件夹折叠/展开图标
__.parent Object 父结点
__.path Array 祖先结点数组
__.pos Number 位置。 在父结点下的位置序号
__.gpos Number 全局位置
__.dpos Number 在显示出来的结点中的位置。
如果某目录结点折叠,则其所有子结点及后裔结点该属性的值为-1
__.depth Number 深度
__.isVisible Boolean 是否可见。折叠隐藏的结点为false
__.isEditing Boolean false 是否正在编辑标题
__.isSearchResult Boolean false 是否是搜索结果
__.isDroppable Boolean true 拖放操作时,是否可放下
__.dragOverArea String null 拖放操作时,鼠标在该结点上的位置。枚举值: prev, self, next, null
__.mousex String 0 拖放操作时鼠标的位置
__.mousey String 0 拖放操作时鼠标的位置
__.titleMaxWidth String none 标题的最大宽度。
它是根据style.titleMaxWidth计算而得
__.titleTip String 鼠标放到标题上显示的提示
当前的使用场合: 标题超过最大宽度后显示省略号,
鼠标放上去显示标题全文
__.customClasses Array [] 加到结点上的自定义CSS类名

一些重要的__属性

dragAndDrop属性

属性 类型 说明
status Number 拖拽操作的类型
0: 当前无拖拽操作
1: 用户将树的结点拖到树的外面
2: 用户拖动树的结点,在树的区域内
3: 用户将外部元素拖拽到树的区域内
dragNode Object 拖动的结点
overNode Object 拖拽操作时,当前鼠标在哪个结点上
overArea String 拖拽操作时,鼠标在当前结点上的位置。枚举值: prev, self, next, null
isDroppable Boolean 是否可放下
isTouch Boolean 是否触屏操作
from Object 拖拽操作的来源。
页面上有多棵树时,将A树的结点拖动到B树,则在B树的一些事件中,
from则表明了拖拽的结点来自哪棵树哪个结点,
其数据如下所示:
{treeId: 'leftTree', nodeId: 3}。

插槽

插槽主要是用于自定义外观

名称 变量 说明
switcher node 展开折叠目录及异步加载数据时的那个图标
icon node 图标
checkbox node 复选框
title node 标题
input node 编辑标题时的输入框
extra node 额外内容。可用来实现按钮功能
contextmenu node 右键菜单
drag-image dnd 拖动结点时,跟随鼠标移动的图形。dnd见前面的dragAndDrop
drag-arrow dnd 拖动结点时,显示在结点标题左边的小箭头。dnd见前面的dragAndDrop

插槽图解

create

功能: 添加结点
原型: create(node, parentNode, pos), create(node, parentNode)
参数

名称 类型 说明
node Object 要添加的结点
parentNode Object|null 父结点
pos Number 位置
可选参数
如果不提供这个参数,则将结点添加为parentNode的最后一个结点

move

功能: 移动结点
原型: move(node, toParent, toPos), move(node, toParent)
参数

名称 类型 说明
node Object
toParent Object|null
toPos Number 位置
可选参数
如果不提供这个参数,则将结点移动为toParent的最后一个结点

search

功能:搜索树,并返回符合条件的结点。
原型:search(keyword, fnMatch), search(keyword)
参数

名称 类型 说明
keyword any 关键词。类型由用户自己决定。
fnMatch function(node, keyword) 回调函数,用于判断该结点是否匹配该关键词。
返回一个布尔值,true则匹配。

如果fnMatch为空且keyword为String类型,则按结点的标题判断是否匹配。

sort

功能:排序
原型:sort(node, recursive, fnCompare), sort(node, recursive)
参数

名称 类型 说明
node Object 排序的结点为该node的子结点。
node=null,则排序深度为1的结点。
recursive Boolean 是否递归
fnCompare function(node1, node2) 回调函数,用于比较两个结点,返回值为一个整数:
  正值,则表示node1排在node2前面
  负值,则表示node1排在node2后面
  0, 则表示不交换node1, node2的位置

如果不传入fnCompare参数,则按结点的标题排序

titleMaxWidth

说明: 设置标题的最大宽度,它的值有两种情况:

  1. 正值,如"3px", "2em", "20%"等等,它跟css属性max-width是一个意思。
  2. 负值,如"-3px", "-2em", "-20%"等等。此时它表示标题的最大长度不能超过距离树容器右边缘的某个位置。
    比如说,如果值为"-20%",则表示在距离树容器右边框20%的位置,标题的最大长度不能超过这个地方。

treeId

说明: 当需要在多棵树之间做拖拽操作时,此ID用于标识所操作的结点的来源。
在用户刚拖动树的结点时,组件会执行event.dataTransfer.setData('twtree', data)
data是一个JSON串,其格式为:

{
  "treeId": "xxxxx",
  "nodeId": "xxxxx"
}

这样在监听到拖放操作相关的事件时,可以使用event.dataTransfer.getData('twtree')来获取结点的数据,知道结点是来源于哪棵树及结点的ID。


常见问题

怎样为所有结点统一设置属性?

使用组件的defaultAttrs属性。

<TWTree :tree="tree" :defaultAttrs="{style:{titleMaxWidth: '3em'}}"></TWTree>

这里表示所有结点的style.titleMaxWidth属性被设置为3em。

在为所有结点统一设置属性的时候,怎样为某些结点单独设置属性?

优先级: 树的结点数据 > defaultAttrs

比如下面的代码的效果是:
id为5的结点的style.titleMaxWidth为5em, 其余的结点的style.titleMaxWidth为3em。

树的结点数据:

[
    {
        id: 1,
        title: 'ROOT',
        hasChild: true,
        children: [
        {
            id: 2,
            title: 'child 1',
        },
        {
            id: 3,
            title: 'child 2',
            hasChild: true,
            children: [
            {
                id: 4,
                title: 'child 2-1'
            },
            {
                id: 5,
                title: 'child 2-2',
                style: {
                    titleMaxWidth: '5em'
                }
            },
            {
                id: 6,
                title: 'child 2-3'
            }
            ],
        },
        {
            id: 7,
            title: 'child 3'
        },
        {
            id: 8,
            title: 'child 4'
        }
        ]
    }
]

模板:

<TWTree :tree="tree" :defaultAttrs="{style:{titleMaxWidth: '3em'}}"></TWTree>

示例

示例

开源协议

  • MIT
  • 无论个人还是公司,都可以免费自由使用

关于用到的图标

在该组件中以及各示例中使用的图标来自: