vue中使用element来创建目录列表
Posted lanhuo666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue中使用element来创建目录列表相关的知识,希望对你有一定的参考价值。
之前按照项目需求使用element中的tree来创建目录列表,如今记录一下。
一、项目需求
1.完整展示目录列表
2.右击节点选择重命名,删除,创建文件夹三个选项
3.拖拽文件夹,其中拖拽文件夹有以下要求:
a. 如果该文件夹内已存在上传文件,则其他文件夹不能拖拽进入该文件夹内
b.整个目录中有且仅有一个根目录,拖拽文件夹的范围只能在该根目录里面
4.重命名文件夹要求:
a.重命名完成后按enter键完成
5.删除文件夹要求:
a.如果该文件夹内已含有上传文件,则删除失败
6.创建文件夹要求:
a.如果该文件夹内已含有上传文件,则创建失败
二、思路整理
1.在mounted中向后台请求项目列表,然后存储treeData
2.鼠标右键弹出的是menu菜单选项框,对于获取点击节点的信息可以使用el-tree中的 @node-contextmenu="rightClick"
3.选择删除文件夹的时候要注意在发送请求的同时也要完成前端的“删除”动作,使用map,indexOf, slice
4.重命名中使用@keyup.enter.native来触发请求,使用focus()聚焦输入框
5.鼠标右击的时候menu的位置是随之改变的,且当鼠标位置加上menu的高度或宽度超出视频范围的时候要合适调节menu的位置。
/* 菜单定位基于鼠标点击位置 */ let height = document.documentElement.clientHeight || document.body.clientHeight if (event.clientY + 168 > height) menu.style.left = event.clientX - 5 + ‘px‘ menu.style.top = event.clientY - 10 - 168 + ‘px‘ else menu.style.left = event.clientX + 10 + ‘px‘ menu.style.top = event.clientY + 5 + ‘px‘
6.menu的显示与隐藏,当鼠标点击其他位置的时候,menu隐藏
document.addEventListener(‘click‘, this.hide, true) document.removeEventListener(‘click‘, this.hide)
7.当文件夹命名过长的时候,出现横向滚动条
.comp-tree margin-top: 1em; overflow-y: hidden; overflow-x: scroll; .el-tree min-width: 100%; display:inline-block !important;
三、源码分析
参考:
在此基础上做的修改
<template> <div v-loading="isLoading" class="comp-tree" @click="hiddenMenu"> <el-tree ref="SlotTree" :data="treeData" :props="defaultProps" :expand-on-click-node="true" highlight-current :node-key="NODE_KEY" @node-click="handleNodeClick" @node-contextmenu="rightClick" @node-drag-start = "handleDragStart" @node-drop="handleDrop" :draggable = draggable default-expand-all > <div class="comp-tr-node" slot-scope=" node, data "> <!-- 编辑状态 --> <template v-if="node.isEdit"> <el-input v-model="data.menuName" autofocus size="mini" :ref="‘slotTreeInput‘+data.recordId" @keyup.enter.native="handleInput(node, data)"> </el-input> </template> <!-- 非编辑状态 --> <template v-else> <!-- 名称: 新增节点增加class(is-new) --> <span> <span> node.label </span> </span> </template> </div> </el-tree> <!-- 鼠标右键产生的选项 --> <div v-show="menuVisible" id="menu"> <el-menu class="el-menu-vertical rightClickMenu" @select="handleRightSelect" text-color="#303133" active-text-color = "#303133" > <el-menu-item index="1" class="menuItem"> <i class="el-icon-edit"></i> <span slot="title">重命名</span> </el-menu-item> <el-menu-item index="2" class="menuItem"> <i class="el-icon-folder-add"></i> <span slot="title">新建文件夹</span> </el-menu-item> <el-menu-item index="3" class="menuItem"> <i class="el-icon-delete"></i> <span slot="title">删除</span> </el-menu-item> </el-menu> </div> <detail-win v-if="isShow" @close="closeWin" :node = NODE v-bind="$attrs" v-on="$listeners"></detail-win> </div> </template> <script> import detailWin from ‘./detail-win‘ import baseWarn from ‘src/common/fn‘ export default components: detailWin , data () return isLoading: false, // 是否加载 NODE_KEY: ‘recordId‘, // id对应字段 defaultProps: // 默认设置 children: ‘children‘, label: ‘menuName‘ , menuVisible: false, isShow: false, clickNode: ‘‘, DATA: null, NODE: null, objectID: null, dragPid: null, dragIndex: null, newParentId: null, oldMenuName: null , computed: treeData () return this.$sysStore.fileTreeData , addNode () return this.$sysStore.addNode , draggable () if (!this.$store.state.user.isOuterUser) return true else return false , watch: , created () , mounted () , methods: // 修改节点 handleInput (node, data) // 退出编辑状态 if (node.isEdit) this.$set(node, ‘isEdit‘, false) if (this.oldMenuName === data.menuName) else this.$axios( url: ‘........‘, method: ‘post‘, data: ... ) .then(res => this.$message( type: ‘success‘, message: ‘重命名成功‘ ) ) .catch(function (error) this.$message( type: ‘error‘, message: ‘重命名失败‘ ) console.log(error) ) , // 重命名 handleEdit (node, data) // 模板文件夹名称不能重命名 if (data.isTemplate === 1) this.$message.error(‘该文件夹无法重命名‘) else // 设置编辑状态 if (!node.isEdit) this.$set(node, ‘isEdit‘, true) // 输入框聚焦 this.$nextTick(() => if (this.$refs[‘slotTreeInput‘ + data.recordId]) this.$refs[‘slotTreeInput‘ + data.recordId].$refs.input.focus() ) , // 新增节点 handleAdd (node, data) // console.log(node,data) if (data.fileSum !== 0) this.$message.error(‘此文件夹已存在上传文件,不能新增文件夹!‘) return this.isShow = true , // 删除节点 handleDelete (node, data) if (data.children && data.children.length !== 0) this.$message.error(‘此文件夹内含有其他文件夹,不可删除!‘) return if (data.fileSum !== 0) this.$message.error(‘此文件夹内含有上传文件,不可删除!‘) else this.$confirm(`是否删除$node.label?`, ‘提示‘, confirmButtonText: ‘确认‘, cancelButtonText: ‘取消‘, type: ‘warning‘ ).then(() => this.deleteProj(node, data) ).catch(() => ) , deleteProj (node, data) this.$axios( url: ‘...‘, method: ‘post‘, data: ... ) .then(res => if (res.success) let _list = node.parent.data.children || node.parent.data// 节点同级数据 let _index = _list.map((c) => c.recordId).indexOf(data.recordId) _list.splice(_index, 1) this.$message.success(‘删除成功‘) // 使右侧列表消失 this.$parent.$parent.disabled = true // 直接改变vuex中treeData的数值 let fileTreeData = this.filter(this.treeData, node.data.kid) this.$store.dispatch(`$this.wpstore/setFileTreeData`, fileTreeData) else this.$message.error(‘删除失败,请重试‘) ) , /** * 删除或者更改treeData中指定kid的子节点 * * @returns arr */ filter (arr, kid) for (var i = 0; i < arr.length; i++) var el = arr[i] if (el.kid === kid) arr.splice(i, 1) else if (el.children && el.children.length) this.filter(el.children, kid) return arr , // 点击节点 handleNodeClick (node) this.menuVisible = false this.$store.dispatch(`$this.wpstore/selectNode`, node) , // 拖拽开始时记录该节点的pid及其在原来数组中的原始数据 handleDragStart (node) this.dragPid = node.data.recordPid let p = this.$refs.SlotTree.getNode(this.dragPid) let _list = p.data.children // 节点同级数据 let _index = _list.map((c) => c.recordId).indexOf(node.data.recordId) this.dragIndex = _index , // 拖拽成功时触发请求 handleDrop (draggingNode, dropNode, dropType, e) // debugger if (dropNode.data.fileSum !== 0 && dropType === ‘inner‘) baseWarn(‘该文件夹内含有上传文件,拖拽失败‘, null, null, null) let _list = dropNode.data.children // 节点同级数据 let _index = _list.map((c) => c.recordId).indexOf(draggingNode.data.recordId) _list.splice(_index, 1) // 将节点返回到原来的位置上 let p = this.$refs.SlotTree.getNode(this.dragPid) // console.log(p,‘p‘) p.data.children.splice(this.dragIndex, 0, draggingNode.data) else if (dropNode.data.recordPid === ‘root‘) baseWarn(‘无法拖拽为根文件夹‘, null, null, null) this.$refs.SlotTree.remove(draggingNode.data.recordId) let p = this.$refs.SlotTree.getNode(this.dragPid) p.data.children.splice(this.dragIndex, 0, draggingNode.data) else // 算出子节点对于父节点的相对位置 let _list = dropNode.parent.data.children // 拖拽节点同级数据 let _index = _list.map((c) => c.recordId).indexOf(draggingNode.data.recordId) if (_index === -1) _list = dropNode.childNodes _index = _list.map((c) => c.data.recordId).indexOf(draggingNode.data.recordId) // 得出目标节点的recordId if (dropNode.parent.data.recordId === this.dragPid) // 相同的父节点 this.newParentId = this.dragPid else this.newParentId = dropNode.parent.data.recordId // 发送请求 this.$axios( url: ‘...‘, method: ‘post‘, data: ... ) .then(res => this.$message( type: ‘success‘, message: ‘拖拽成功‘ ) ) .catch(function (error) console.log(error) ) , // 鼠标右击 rightClick (event, object, value, element) this.oldMenuName = object.menuName if (this.$store.state.user.isOuterUser) this.menuVisible = false else if (this.objectID !== object.recordId) this.objectID = object.recordId this.menuVisible = true this.DATA = object this.NODE = value else this.menuVisible = !this.menuVisible // document.addEventListener(‘click‘, (e) => // this.menuVisible = false // ) this.hiddenMenu() let menu = document.querySelector(‘.rightClickMenu‘) /* 菜单定位基于鼠标点击位置 */ let height = document.documentElement.clientHeight || document.body.clientHeight if (event.clientY + 168 > height) menu.style.left = event.clientX - 5 + ‘px‘ menu.style.top = event.clientY - 10 - 168 + ‘px‘ else menu.style.left = event.clientX + 10 + ‘px‘ menu.style.top = event.clientY + 5 + ‘px‘ menu.style.position = ‘fixed‘ , handleRightSelect (key) this.menuVisible = false if (key == 1) this.handleEdit(this.NODE, this.DATA) else if (key == 2) this.handleAdd(this.NODE, this.DATA) else if (key == 3) this.handleDelete(this.NODE, this.DATA) , hiddenMenu () document.addEventListener(‘click‘, this.hide, true) document.removeEventListener(‘click‘, this.hide) , hide() this.menuVisible = false , closeWin (val) this.isShow = val </script> <style lang="scss" scoped> .el-menu border: solid 1px #e6e6e6 .comp-tree margin-top: 1em; overflow-y: hidden; overflow-x: scroll; .el-tree min-width: 100%; display:inline-block !important; .rightClickMenu z-index: 999 </style>
这里仅供参考,具体的编写代码还需根据各位实际项目需求来修改
以上是关于vue中使用element来创建目录列表的主要内容,如果未能解决你的问题,请参考以下文章
element-ui中el-select与el-tree的结合使用实现下拉菜单