注册页面路由
router/router.js
{
path: 'folder_tree',
name: 'folderTree',
component: () => import('@/views/folder-tree/folder-tree.vue')
}
定义api请求
api/data.js
export const getFolderList = () => {
return axios.request({
url: '/getFolderList',
method: 'get'
})
}
export const getFileList = () => {
return axios.request({
url: '/getFileList',
method: 'get'
})
}
mock数据
mock/index.js
import Mock from 'mockjs'
import { getFileList, getFolderList } from './response/data'
const Random = Mock.Random
Mock.mock(//getFileList/, 'get', getFileList)
Mock.mock(//getFolderList/, 'get', getFolderList)
export default Mock
mock/response/data.js
import { doCustomTimes } from '@/lib/tools'
import Mock from 'mockjs'
const Random = Mock.Random
export const getFolderList = () => {
const template1 = {
'name|1': '@word',
'creat_time': '@datetime',
'folder_id': 0,
'id|+1': 1
}
const template2 = {
'name|1': '@word',
'creat_time': '@datetime',
'folder_id|+1': 1,
'id|+1': 4
}
let arr = []
doCustomTimes(3, () => {
arr.push(Mock.mock(template1))
})
doCustomTimes(2, () => {
arr.push(Mock.mock(template2))
})
return arr
}
自定义函数
lib/tools.js
// 调用times次callback
export const doCustomTimes = (times, callback) => {
let i = -1
while (++i < times) {
callback()
}
}
使用
iviews/folder-tree/folder-tree.vue
<template>
<h1>folder-tree page</h1>
</template>
<script>
import { getFolderList, getFileList } from '@/api/data'
export default {
data () {
return {
folderList: [],
fileList: []
}
},
mounted () {
Promise.all([getFolderList(), getFileList()]).then(res => {
console.log(res)
})
}
}
</script>
将文件放在对应的文件夹里
lib/util.js
import clonedeep from 'clonedeep'
export const putFileInFolder = (folderList, fileList) => {
const folderListCloned = clonedeep(folderList)
const fileListCloned = clonedeep(fileList)
return folderListCloned.map(folderItem => {
const folderId = folderItem.id
let index = fileListCloned.length
while (--index >= 0) {
const fileItem = fileListCloned[index]
if (fileItem.folder_id === folderId) {
const file = fileListCloned.splice(index, 1)[0]
file.title = file.name
if (folderItem.children) folderItem.children.push(file)
else folderItem.children = [file]
}
}
folderItem.type = 'folder'
return folderItem
})
}
folder-tree.vue
Promise.all([getFolderList(), getFileList()]).then(res => {
console.log(putFileInFolder(res[0], res[1])) // 如图
})
图:
递归函数(整合文件夹)
util.js
export const transferFolderToTree = folderList => {
if (!folderList.length) return []
const folderListCloned = clonedeep(folderList)
const handle = id => {
let arr = []
folderListCloned.forEach(folder => {
if (folder.folder_id === id) {
const children = handle(folder.id)
if (folder.children) {
folder.children = [].concat(folder.children, children)
} else {
folder.children = children
}
folder.title = folder.name
arr.push(folder)
}
})
return arr
}
return handle(0)
}
srcviewsfolder-treefolder-tree.vue
<template>
<Tree :data="folderTree"></Tree>
</template>
<script>
import { getFolderList, getFileList } from '@/api/data'
import { putFileInFolder, transferFolderToTree } from '@/lib/util'
export default {
data () {
return {
folderList: [],
fileList: [],
folderTree: []
}
},
mounted () {
Promise.all([getFolderList(), getFileList()]).then(res => {
this.folderTree = transferFolderToTree(putFileInFolder(res[0], res[1]))
})
}
}
</script>
3 ## 自定义组件结构
srcviewsfolder-treefolder-tree.vue
<template>
<div class="folder-wrapper">
<Tree :data="folderTree" :render="renderFunc"></Tree>
</div>
</template>
<script>
import { getFolderList, getFileList } from '@/api/data'
import { putFileInFolder, transferFolderToTree } from '@/lib/util'
export default {
data () {
return {
folderList: [],
fileList: [],
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>
)
}
}
},
mounted () {
Promise.all([getFolderList(), getFileList()]).then(res => {
this.folderTree = transferFolderToTree(putFileInFolder(res[0], res[1]))
})
}
}
</script>
<style lang="less">
.folder-wrapper {
width: 300px;
.tree-item {
display: inline-block;
width: ~"calc(100% - 50px)";
height: 30px;
line-height: 30px;
}
}
</style>