VUE-tree组件实现(封装文件目录组件,操作目录-render,多个属性v-moadal代替方案,增加钩子函数)

思维:
文件夹以及文件数据来自于两组数据
父级folder-tree中:
在template中:

在script中:

 import { getFolderList, getFileList } from '@/api/data'
   import { putFileInFolder, transferFolderToTree } from '@/lib/util'
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(() => {
      console.log(222)
      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]
})
}
}

子组件中:
template:

script:

import { putFileInFolder, transferFolderToTree, expandSpecifiedFolder } from '@/lib/util'
import clonedeep from 'clonedeep'
export default {
name: 'FolderTree',
data () {
return {
  folderTree: [],
  currentRenameingId: '',
  currentRenameingContent: '',
  renderFunc: (h, { root, node, data }) => {
    const dropList = data.type === 'folder' ? this.folderDrop : this.fileDrop
    const dropdownRender = dropList.map(item => {
      return ({ item.title })
    })
    const isRenaming = this.currentRenameingId === `${data.type || 'file'}_${data.id}`
    return (
      
{ data.type === 'folder' ? : '' } { isRenaming ? : { data.title } } { dropList && !isRenaming ? { dropdownRender } : '' }
) } } }, props: { folderList: { type: Array, default: () => {} }, fileList: { type: Array, default: () => {} }, // folderDrop: { // type: Array,s // default: () => {} // } // 此处如果是空数组,说明这里不需要下拉菜单,这里不用设置默认值; // 这里就不是直接判断数组是否为空,而是直接判断这里folderDrop是否为undefined,如果为undefined说明这里没有传入值 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.currentRenameingId = `${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.currentRenameingContent = 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.currentRenameingContent list.splice(i, 1, folderItem) break } } return list }, saveRename (data) { const id = data.id const folderId = data.folder_id const type = data.type if (type === 'folder') { const list = this.updateList(clonedeep(this.folderList), id) this.$emit('update:folderList', list) this.$nextTick(() => { expandSpecifiedFolder(this, this.folderTree, folderId) }) } else { const list = this.updateList(this.fileList, id) this.$emit('update:fileList', list) this.$nextTick(() => { expandSpecifiedFolder(this, this.folderTree, folderId) }) } this.currentRenameingId = '' }, delete () { // } }, mounted () { this.transData() } }

在@/lib/util中

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
     })
}
// 只对文件夹进行处理
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)
  }
// 根据目录中id 展开指定的文件夹;folderTree代表展开文件夹树状列表,id是展开文件的id
export const expandSpecifiedFolder = (vm, folderTree, id) => {
return folderTree.map(item => {
if (item.type === 'folder') {
  if (item.id === id) {
    // item.expand = true
    vm.$set(item, 'expand', true)
  } else {
    if (item.children && item.children.length) {
      item.children = expandSpecifiedFolder(vm, item.children, id)
      if (item.children.some(child => {
        return child.expand === true
      })) {
        // item.expand = true
        vm.$set(item, 'expand', true)
      } else {
        // item.expand = false
        vm.$set(item, 'expand', false)
      }
    }
  }
}
return item
})
}

在MOCK中

import { doCustomTimes } from '@/lib/tools'
import Mock from 'mockjs'
export const getFileList = () => {
      const template = {
       'name|5': '@cword',
    'creat_time': '@datetime',
    'folder_id|1-5': 0,
    'id|+1': 10000
      }
      let arr = []
      doCustomTimes(10, () => {
    arr.push(Mock.mock(template))
     })
    return arr
}

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中

// 与业务无关的工具函数
export const doCustomTimes = (times, callback) => {
  let i = -1
  while (++i < times) {
callback()
      }
}

在api/data中

export const getFolderList = () => {
  return axios.request({
url: '/getFolderList',
method: 'get'
  })
}
export const getFileList = () => {
return axios.request({
url: '/getFileList',
method: 'get'
  })
}

你可能感兴趣的:(vue.js)