Vue iview Tree组件实现文件目录-高级实现
封装文件目录组件

src\views\folder-tree\folder-tree.vue
<template>
<div class="folder-wrapper">
<folder-tree :folder-list="folderList" :file-list="fileList"/>
</div>
</template>
<script>
import { getFolderList, getFileList } from '@/api/data';
import FolderTree from '_c/folder-tree';
export default {
components: {
FolderTree
},
data () {
return {
folderList: [],
fileList: []
}
},
mounted () {
Promise.all([getFolderList(), getFileList()]).then(res => {
this.folderList = res[0]
this.fileList = res[1]
})
}
}
</script>
<style lang="less">
.folder-wrapper {
width: 300px;
}
</style>
src\components\folder-tree\folder-tree.vue
<template>
<div class="folder-wrapper">
<Tree :folder-list="folderList" :file-list="fileList" :data="folderTree" :render="renderFunc"></Tree>
</div>
</template>
<script>
import { putFileInFolder, transferFolderToTree } from '@/lib/util'
export default {
name: 'FolderTree',
data () {
return {
folderTree: [],
renderFunc: (h, { root, node, data }) => {
return (
<div class="tree-item">
{data.type === 'folder' ? (
<icon
type="ios-folder"
color="#2d8cf0"
style="margin-right: 5px;"
/>
) : (
''
)}
{data.title}
</div>
)
}
}
},
props: {
folderList: {
type: Array,
default: () => []
},
fileList: {
type: Array,
default: () => []
}
},
methods: {
transData () {
this.folderTree = transferFolderToTree(
putFileInFolder(this.folderList, this.fileList)
)
}
},
watch: {
folderList () {
this.transData()
},
fileList () {
this.transData()
}
},
mounted () {
this.transData()
}
}
</script>
<style lang="less">
.tree-item {
display: inline-block;
width: ~"calc(100% - 50px)";
height: 30px;
line-height: 30px;
}
</style>
操作目录
多个属性v-model替代方案
增加钩子函数

src\views\folder-tree\folder-tree.vue
<template>
<div class="folder-wrapper">
<!-- <Tree :data="folderTree" :render="renderFunc"></Tree> -->
<folder-tree
:folder-list.sync="folderList"
:file-list.sync="fileList"
:folder-drop="folderDrop"
:file-drop="fileDrop"
:beforeDelete="beforeDelete"
/>
</div>
</template>
<script>
import { getFolderList, getFileList } from '@/api/data'
import FolderTree from '_c/folder-tree'
export default {
components: {
FolderTree
},
data () {
return {
folderList: [],
fileList: [],
folderDrop: [
{
name: 'rename',
title: '重命名'
},
{
name: 'delete',
title: '删除文件夹'
}
],
fileDrop: [
{
name: 'rename',
title: '重命名'
},
{
name: 'delete',
title: '删除文件'
}
]
}
},
methods: {
beforeDelete () {
return new Promise((resolve, reject) => {
setTimeout(() => {
let error = new Error('error')
if (!error) {
resolve()
} else reject(error)
}, 2000)
})
}
},
mounted () {
Promise.all([getFolderList(), getFileList()]).then(res => {
this.folderList = res[0]
this.fileList = res[1]
})
}
}
</script>
<style lang="less">
.folder-wrapper {
width: 300px;
}
</style>
src\components\folder-tree\folder-tree.vue
<template>
<Tree :data="folderTree" :render="renderFunc"></Tree>
</template>
<script>
import {
putFileInFolder,
transferFolderToTree,
expandSpecifiedFolder
} from '@/lib/util'
import clonedeep from 'clonedeep'
export default {
name: 'FolderTree',
data () {
return {
folderTree: [],
currentRenamingId: '',
currentRenamingContent: '',
renderFunc: (h, { root, node, data }) => {
const dropList =
data.type === 'folder' ? this.folderDrop : this.fileDrop
const dropdownRender = dropList.map(item => {
return <dropdownItem name={item.name}>{item.title}</dropdownItem>
})
const isRenaming =
this.currentRenamingId === `${data.type || 'file'}_${data.id}`
return (
<div class="tree-item">
{data.type === 'folder' ? (
<icon
type="ios-folder"
color="#2d8cf0"
style="margin-right: 10px;"
/>
) : (
''
)}
{isRenaming ? (
<span>
<i-input
value={data.title}
on-input={this.handleInput}
class="tree-rename-input"
/>
<i-button
size="small"
type="text"
on-click={this.saveRename.bind(this, data)}
>
<icon type="md-checkmark" />
</i-button>
<i-button size="small" type="text">
<icon type="md-close" />
</i-button>
</span>
) : (
<span>{data.title}</span>
)}
{dropList && !isRenaming ? (
<dropdown
placement="right-start"
on-on-click={this.handleDropdownClick.bind(this, data)}
>
<i-button size="small" type="text" class="tree-item-button">
<icon type="md-more" size={12} />
</i-button>
<dropdownMenu slot="list">{dropdownRender}</dropdownMenu>
</dropdown>
) : (
''
)}
</div>
)
}
}
},
props: {
folderList: {
type: Array,
default: () => []
},
fileList: {
type: Array,
default: () => []
},
folderDrop: Array,
fileDrop: Array,
beforeDelete: Function
},
watch: {
folderList () {
this.transData()
},
fileList () {
this.transData()
}
},
methods: {
transData () {
this.folderTree = transferFolderToTree(
putFileInFolder(this.folderList, this.fileList)
)
},
isFolder (type) {
return type === 'folder'
},
handleDelete (data) {
const folderId = data.folder_id
const isFolder = this.isFolder(data.type)
let updateListName = isFolder ? 'folderList' : 'fileList'
let list = isFolder
? clonedeep(this.folderList)
: clonedeep(this.fileList)
list = list.filter(item => item.id !== data.id)
this.$emit(`update:${updateListName}`, list)
this.$nextTick(() => {
expandSpecifiedFolder(this, this.folderTree, folderId)
})
},
handleDropdownClick (data, name) {
if (name === 'rename') {
this.currentRenamingId = `${data.type || 'file'}_${data.id}`
} else if (name === 'delete') {
this.$Modal.confirm({
title: '提示',
content: `您确定要删除${
this.isFolder(data.type) ? '文件夹' : '文件'
}《${data.title}》吗?`,
onOk: () => {
this.beforeDelete
? this.beforeDelete()
.then(() => {
this.handleDelete(data)
})
.catch(() => {
this.$Message.error('删除失败')
})
: this.handleDelete(data)
}
})
}
},
handleInput (value) {
this.currentRenamingContent = value
},
updateList (list, id) {
let i = -1
let len = list.length
while (++i < len) {
let folderItem = list[i]
if (folderItem.id === id) {
folderItem.name = this.currentRenamingContent
list.splice(i, 1, folderItem)
break
}
}
return list
},
saveRename (data) {
const id = data.id
const type = data.type
if (type === 'folder') {
const list = this.updateList(clonedeep(this.folderList), id)
this.$emit('update:folderList', list)
} else {
const list = this.updateList(this.fileList, id)
this.$emit('update:fileList', list)
}
this.currentRenamingId = ''
}
},
mounted () {
this.transData()
}
}
</script>
<style lang="less">
.tree-item {
display: inline-block;
width: ~"calc(100% - 50px)";
height: 30px;
line-height: 30px;
& > .ivu-dropdown {
float: right;
}
ul.ivu-dropdown-menu {
padding-left: 0;
}
li.ivu-dropdown-item {
margin: 0;
padding: 7px 16px;
}
.tree-rename-input {
width: ~"calc(100% - 80px)";
}
}
</style>
Vue iview Tree组件实现文件目录-高级实现的更多相关文章
- Vue iview Tree组件实现文件目录-基础实现
注册页面路由 router/router.js { path: 'folder_tree', name: 'folderTree', component: () => import('@/vie ...
- VUE -- iview table 组件 中使用 upload组件 上传组件 on render 事件不会触发问题
碰到的问题是: upload 组件在 on中写的监听事件不会被触发 在 props 中来监听:==>
- vue iview tree checked改变 不渲染的问题
子级的状态 改为checked=false 需要把父的状态改为 false
- vue - iview UI组件的col标签报错 x-invalid-end-tag
https://blog.csdn.net/xiao199306/article/details/80430087
- Vue ElementUI Tree组件 回显问题(设置选择父级时会全选所有的子级,有此业务场景是不适合的)
业务场景下有这样的问题 业务需求需要保存前端 半选节点 解决方案 let checked = this.$refs.menuTree.getCheckedKeys(); //此方法获取半选节点 let ...
- 【技术博客】使用iview的Tree组件写一棵文件树
本次项目的前端部分使用vue框架+iview组件构建,其中IDE的文件树部分使用了iview的Tree组件,但是Tree组件本身的接口功能极其有限,网上的相关资料也不多,在使用时费了一番功夫才摸索清楚 ...
- 基于iview 封装一个vue 表格分页组件
iview 是一个支持中大型项目的后台管理系统ui组件库,相对于一个后台管理系统的表格来说分页十分常见的 iview是一个基于vue的ui组件库,其中的iview-admin是一个已经为我们搭好的后天 ...
- iView中Tree组件children中动态checked选中后取消勾选再选中无效问题
如题,我有一个Tree组件,动态更新check选中子级列表的时候,取消勾选了再点击选中时复选框样式不是勾选状态,但是数据已经有了. 对此解决方案是:将初始化时Tree组件data数据深拷贝一遍再去判断 ...
- Vue 2.0 组件库总结
UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基于Vue和WeUI的组件库 mint-ui - Vue 2的移动UI元素 iview - 基于 Vuejs 的开 ...
随机推荐
- Typora安装教程
一:Typora介绍 Markdown是一种轻量级标记语言.通过简单的标记语法,它可以使普通文本内容具有一定的格式.所谓轻量级标记语言指的是一类用简单句法描述简单格式的文本语言. 二:下载地址 ...
- Excel 科学计数法数值转换
问题场景 如果导出的数据文件后缀为.CSV,一般数值类型的数据超过12位后,单元格的数据就用科学计数法来表示了. 比如身份证号.较长的id,数值会超过12位,而科学计数法表示,不方便查看或操作,很多情 ...
- Windows下make clean指令错误[错误码2](系统找不到指定文件)的解决方案
问题来源 因为笔者想用GCC编译器进行Windows下的C语言编程,安装了Mingw-w64的x86_64-posix-seh版本,并按照Visual Studio Code官方的教程,将Mingw- ...
- 操作系统-中断(2)IA-32/Linux的向量中断方式
一.Intel定义下的异常和中断 不同体系和教材往往对异常和中断有不同的定义. Intel定义:中断是一种典型的由I/O设备触发的.与当前正在执行的指令无关的异步事件:而异常是处理器执行一条指令时,由 ...
- 方差分析、T检验、卡方分析如何区分?
差异研究的目的在于比较两组数据或多组数据之间的差异,通常包括以下几类分析方法,分别是方差分析.T检验和卡方检验. 三个方法的区别 其实核心的区别在于:数据类型不一样.如果是定类和定类,此时应该使用卡方 ...
- 牛客网PAT-练兵场-挖掘机技术哪家强
题目地址:https://www.nowcoder.com/pat/6/problem/4058 题解:用数组下标当学校编号.输入一次数据的时候,直接在相应数组下标位置累加内容,同时更新最大的总分的学 ...
- 网站seo优化有什么优缺点
http://www.wocaoseo.com/thread-94-1-1.html seo是什么?这个可能是刚刚知道网络营销或搜索引擎营销的朋友们问的话,笔者在这里装一下,呵呵.说真的现 ...
- 使用 Postman 做 API 自动化测试
Postman 最基本的功能用来重放请求,并且配合良好的 response 格式化工具. 高级点的用法可以使用 Postman 生成各个语言的脚本,还可以抓包,认证,传输文件. 仅仅做到这些还不能够满 ...
- 阿里云体验实验室 教你《搭建Hadoop环境》
体验平台简介 面向开发者和中小企业打造的一站式.全云端的开发平台,打开浏览器就可以开发.调试.上线,所测即所得,并结合无服务器的模式,重新定义云原生时代的研发工作方法论.旨在降低开发者上手成本和中小企 ...
- 【Android】AndroidStudio(Eclipse)如何使用天天模拟器进行调试apk应用。
作者:程序员小冰,GitHub主页:https://github.com/QQ986945193 新浪微博:http://weibo.com/mcxiaobing 大家都知道,我们这些Android开 ...