zoukankan      html  css  js  c++  java
  • Vue iview Tree组件实现文件目录-高级实现

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

    1. 封装文件目录组件

    在这里插入图片描述

    srcviewsfolder-treefolder-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>
    

    srccomponentsfolder-treefolder-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. 增加钩子函数

    在这里插入图片描述

    srcviewsfolder-treefolder-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>
    

    srccomponentsfolder-treefolder-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>
    
  • 相关阅读:
    Beta冲刺——day2
    Beta冲刺——day1
    OpenGL立方体在世界坐标系中_缩放_旋转_平移_顶点片源着色器_光照作用_棋盘纹理贴图
    FIRST集和FOLLOW集
    现代计算机接口实验 (五)0809实验
    现代计算机接口实验 (四)0832实验
    现代计算机接口实验 (二)8253实验
    现代计算机接口实验 (三)8255实验
    现代计算机接口实验 (一)熟悉环境
    可编程控制器实训
  • 原文地址:https://www.cnblogs.com/izhaong/p/12154275.html
Copyright © 2011-2022 走看看