一、定义
html
<el-tree
class="myTreeClass"
:data="dirTreeData"
:props="dirTreeProps"
:filter-node-method="filterDirTree"
:expand-on-click-node="false"
node-key="id"
@node-click="dirTreeNodeClick"
:allow-drop="dirTreeAllowDrop"
@node-drop="dirTreeNodeDrop"
ref="dirTreeRef"
style="margin-top: 10px"
draggable>
</el-tree>
-
data:dirTreeData 数组
-
props:dirTreeProps 可指定树的label/children等数据
javascriptconst dirTreeProps = ref({ children:'children', label: function (node){ return node.dirItem.name } })
二、插槽
插槽中可以定义icon、目录名称样式等数据
html
<template #default="{ node,data }">
<div style="display: flex;flex-grow:1">
<div style="display: flex">
<el-icon style="margin-right: 3px">
<FolderOpened v-if="node.expanded" />
<Folder v-else />
</el-icon>
<div>
<div v-if="data.isEdit" style="margin-left: 8px">
<el-input class="dirNameInput" v-model="data.dirItem.name" size="small" @blur="updateDirName(node)"></el-input>
</div>
<div v-else style="margin-left: 8px">{{node.label}}</div>
</div>
</div>
<div style="display:flex;margin-left: auto">
<div>{{data.dirItem.countNow}}</div>
<div style="margin-left: 2px">({{data.dirItem.countAll}})</div>
</div>
</div>
</template>
三、拖拽目录限制判断
通过el-tree绑定:allow-drop="dirTreeAllowDrop",实现对拖拽目标不能是根节点的限制
javascript
const dirTreeAllowDrop = (moveNode,inNode)=>{
// 拖拽的目标节点不能是根节点
return inNode.data.id !== rootNodeId.value;
}
四、拖拽目录完成后事件处理
通过el-tree绑定@node-drop="dirTreeNodeDrop",实现对拖拽目标不能是根节点的限制
javascript
const dirTreeNodeDrop = (moveNode,inNode,type)=>{
if (type === 'inner'){
emitClickTreeNode(inNode)
}else {
emitClickTreeNode(moveNode)
}
}
五、设置某个节点选中状态
javascript
dirTreeRef.value.setCurrentKey(targetNode.key)
六、调用某个节点点击事件
javascript
dirTreeRef.value.$emit('node-click',targetNode.data,targetNode,null)
七、根据nodeId获取当前节点data数据
javascript
const findTreeDataById = (nodeId)=>{
const traverse = (nodes)=>{
for(const node of nodes){
if (node.id === nodeId) return node;
if (node.children && node.children.length > 0){
const found = traverse(node.children)
if (found) return found
}
}
}
return traverse(dirTreeData.value)
}
八、根据nodeId获取父节点data数据
javascript
const findParentTreeDataById = (nodeId)=>{
const traverse = (nodes)=>{
for(const node of nodes){
if (node.children && node.children.length > 0){
if (node.children.some(child=>child.id === nodeId)){
return node;
}
const parentNode = traverse(node.children)
if (parentNode) return parentNode
}
}
}
return traverse(dirTreeData.value)
}
九、根据nodeId获取Tree组件中当前节点node
javascript
const parentNode = dirTreeRef.value.getNode(parentData.id)
十、新增目录
javascript
const addDir = async ()=>{
if (!currentSelectedNode.value){
ElMessage.error('未找当前节点,请刷新后重试')
return
}
// 后台请求新增目录
let newDir = {
xxxx
}
const dirAddResp = await dirService.dirAdd(newDir)
const {data:{data:dirAddId}} = dirAddResp
if(!dirAddId){
ElMessage.error('保存失败,未获取到新增目录id')
return
}
// 增加对应树节点
let newDirData = {
id:dirAddId,
dirItem:{
id:dirAddId,
name:'新建目录',
countNew:0,
countAll:0
},
isEdit:true,
children:[]
}
currentSelectedNode.value.children.push(newDirData)
await nextTick(()=>{
// 展开其父节点
const parentData = findParentTreeDataById(newDirData.id)
const parentNode = dirTreeRef.value.getNode(parentData.id)
parentNode.expand()
// 定位到当前节点
const newDirNode = dirTreeRef.value.getNode(newDirData.id)
emitClickTreeNode(newDirNode)
// 输入框焦点定位
nextTick(()=>{
setTimeout(()=>{
const input = document.querySelector('.dirNameInput .el-input__inner')
if (input){
input.focus()
}
},500)
})
})
}
十一、删除目录
javascript
const deleteDir = async ()=>{
// 后台请求删除节点
const dirDeleteResp = await dirService.caseDirDelete(currentSelectedNode.value.id)
const {data:{errno:respErrno}} = dirDeleteResp
if (respErrno !== 0) {
ElMessage.error('节点删除失败,请刷新后重试')
return
}
// 从父节点中移除当前节点
const parentData = findParentTreeDataById(currentSelectedNode.value.id)
const index = parentData.children.indexOf(currentSelectedNode.value)
parentData.children.splice(index,1)
// 将焦点定位至父节点
const parentNode = dirTreeRef.value.getNode(parentData.id)
await nextTick(()=>{
emitClickTreeNode(parentNode)
})
}
十二、目录重命名
先把目录的输入框显示出来,并将焦点置于输入框
javascript
const editDirName = async ()=>{
const treeData = findTreeDataById(currentSelectedNode.value.id)
treeData.isEdit = true
await nextTick(()=>{
const input = document.querySelector('.dirNameInput .el-input__inner')
if (input){
input.focus()
}
})
}
然后再input @blur=updateDirName时,调用后台保存
javascript
const updateDirName = async(node)=>{
// 后台请求重命名目录
const dirRenameResp = await dirService.dirRename(node.data.id,node.data.dirItem.name)
const {data:{errno:respErrno}} = dirRenameResp
if (respErrno !== 0) {
ElMessage.error('节点重命名失败,请刷新后重试')
return
}
node.data.isEdit = false
}