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 的开 ...
随机推荐
- 在不影响程序使用的情况下添加shellcode
参考 在文章Backdooring PE Files with Shellcode中介绍了一种在正常程序中注入shellcode的方式,让程序以前的逻辑照常能够正常运行,下面复现一下并解决几个小问题. ...
- 大数据理论篇HDFS的基石——Google File System
Google File System 但凡是要开始讲大数据的,都绕不开最初的Google三驾马车:Google File System(GFS), MapReduce,BigTable. 为这一切的基 ...
- linux下udev和mdev的使用
linux下设备文件系统有devfs.udev和mdev这三种. 一.devfs devfs是由Linux 2.4内核引入的,引入时被许多工程师给予了高度评价,它的出现使得设备驱动程序能自主地管理自己 ...
- 百钱百鸡小游戏PHP代码
<?php // 计算小鸡的数量 $count=[]; // 第一个for循环计算公鸡 for ($gj=1;$gj<(100/5);$gj++){ // 第二个for循环计算母鸡 for ...
- Gradle Wrapper
Gradle Wrapper 当把本地一个项目放入到远程版本库的时候,如果这个项目是以gradle构建的,那么其他人从远程仓库拉取代码之后如果本地没有安装过gradle会无法编译运行,如果对gradl ...
- Java面试题(设计模式篇+Spring/Spring MVC篇)
设计模式 88.说一下你熟悉的设计模式? 自行熟悉. 89.简单工厂和抽象工厂有什么区别? 简单理解简单工厂:对 一个对象的创建进行封装.抽象工厂:对 一组对象的创建进行封装. 比如生产 陶瓷马 和 ...
- shazidouhuiapp
在选择了软件工程专业之后,指导教师也让我们参加到了学长学姐的作业之中来,使用学长学姐们的软件并写出自己的使用评价以及自己的一些小评价. 我这次体验的是第三组的学长学姐们的软件,他们的队名叫天公疼憨仔, ...
- flutter 设置状态栏的背景与颜色
flutter 设置状态栏的背景与颜色 导包 import 'dart:io'; import 'package:flutter/services.dart'; 在main()函数中添加以下函数, v ...
- React State
React 里只需要更新组件的state,然后根据新的 state 重新徐娜然用户界面(不要操作DOM). class Clock extends React.Component { construc ...
- 【Flutter 实战】全局点击空白处隐藏键盘
老孟导读:为什么要实现点击空白处隐藏键盘?因为这是 iOS 平台的默认行为,Android 平台由于其弹出的键盘右上角默认带有关闭键盘的按钮,所以点击空白处不会隐藏键盘. 对于单个页面来说,通过为 T ...