Tree组件实现文件目录-基础实现

  1. 封装文件目录组件

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>
  1. 操作目录

  2. 多个属性v-model替代方案

  3. 增加钩子函数

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组件实现文件目录-高级实现的更多相关文章

  1. Vue iview Tree组件实现文件目录-基础实现

    注册页面路由 router/router.js { path: 'folder_tree', name: 'folderTree', component: () => import('@/vie ...

  2. VUE -- iview table 组件 中使用 upload组件 上传组件 on render 事件不会触发问题

    碰到的问题是: upload 组件在 on中写的监听事件不会被触发 在 props 中来监听:==>

  3. vue iview tree checked改变 不渲染的问题

    子级的状态 改为checked=false  需要把父的状态改为 false

  4. vue - iview UI组件的col标签报错 x-invalid-end-tag

    https://blog.csdn.net/xiao199306/article/details/80430087

  5. Vue ElementUI Tree组件 回显问题(设置选择父级时会全选所有的子级,有此业务场景是不适合的)

    业务场景下有这样的问题 业务需求需要保存前端 半选节点 解决方案 let checked = this.$refs.menuTree.getCheckedKeys(); //此方法获取半选节点 let ...

  6. 【技术博客】使用iview的Tree组件写一棵文件树

    本次项目的前端部分使用vue框架+iview组件构建,其中IDE的文件树部分使用了iview的Tree组件,但是Tree组件本身的接口功能极其有限,网上的相关资料也不多,在使用时费了一番功夫才摸索清楚 ...

  7. 基于iview 封装一个vue 表格分页组件

    iview 是一个支持中大型项目的后台管理系统ui组件库,相对于一个后台管理系统的表格来说分页十分常见的 iview是一个基于vue的ui组件库,其中的iview-admin是一个已经为我们搭好的后天 ...

  8. iView中Tree组件children中动态checked选中后取消勾选再选中无效问题

    如题,我有一个Tree组件,动态更新check选中子级列表的时候,取消勾选了再点击选中时复选框样式不是勾选状态,但是数据已经有了. 对此解决方案是:将初始化时Tree组件data数据深拷贝一遍再去判断 ...

  9. Vue 2.0 组件库总结

    UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基于Vue和WeUI的组件库 mint-ui - Vue 2的移动UI元素 iview - 基于 Vuejs 的开 ...

随机推荐

  1. 基于Prometheus和Grafana打造业务监控看板

    前言 业务监控对许许多多的场景都是十分有意义,业务监控看板可以让我们比较直观的看到当前业务的实时情况,然后运营人员可以根据这些情况及时对业务进行调整操作,避免业务出现大问题. 老黄曾经遇到过一次比较尴 ...

  2. java容器源码分析及常见面试题笔记

      概览 容器主要包括 Collection 和 Map 两种,Collection 存储着对象的集合,而 Map 存储着键值对(两个对象)的映射表. List Arraylist: Object数组 ...

  3. @SuppressWarnings注解用法详解(转)

    原文连接https://blog.csdn.net/sysware_carol/article/details/52100580 今天来谈谈@SuppressWarnings注解的作用. J2SE 提 ...

  4. go chan 缓存与阻塞

    原文链接:Go语言第十一课 并发(三)Channel缓存与阻塞 Channel的缓存 前面介绍过channel的创建方法: channel_test := make(chan string) 其实它完 ...

  5. 操作系统-PV习题

    (1)阅览室问题:加入阅览室入口有一本登记册,每个人都必须按顺序签名进去. 想法:登记册可以用结构数组A[]表示,包含name和number.此外,还需要信号量seatcount表示剩余座位数. 使用 ...

  6. 超市管理系统C语言

    登录系统 # include <stdio.h> //头文件 # include <string.h> //字符串头文件 # include <stdlib.h> ...

  7. 服务器里Centos 7安装KVM,并通过KVM安装Centos 7

    一.安装KVM 1.进入系统后,检查cpu参数是否支持虚拟化: [root@localhost ~]# grep -Ei 'vmx|svm' /proc/cpuinfo 如果有出现vmx或者svm关键 ...

  8. activiti app 6.0 乱码

    登录activiti-admin 乱码,解决后如下: 在catalina.bat文件中设置 -Dfile.encoding=UTF-8 1,windows 修改catalina.bat tomcat7 ...

  9. Jeecg-Cloud学习之路(一)

    首先,Spring-Cloud目前是行业的潮流,貌似不会就落后了,笔者为了不脱离大部队只能深入学习一下了. 其次.跳槽到一家公司,给公司推荐了Jeecg-Boot的开发平台,那么为了后面扩展为clou ...

  10. 从APP的启动说起

    iOS里面APP的启动,过程有些复杂,今天我们来抽丝剥茧,一步步探讨一下APP的启动会经历哪些过程. 首先,用户点击iPhone里面的某个APP的icon,Kernel内核会开始初始化空间并创建进程, ...