亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

vue實(shí)現(xiàn)自定義樹(shù)形組件的示例代碼

 更新時(shí)間:2023年08月28日 10:16:37   作者:SunnyRun!  
這篇文章主要介紹了vue實(shí)現(xiàn)自定義樹(shù)形組件的示例代碼,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

效果展示:

在這里插入圖片描述

近期的一個(gè)功能需求,實(shí)現(xiàn)一個(gè)樹(shù)形結(jié)構(gòu):可點(diǎn)擊,可拖拽,右側(cè)數(shù)據(jù)可以拖拽到對(duì)應(yīng)的節(jié)點(diǎn)內(nèi),可創(chuàng)建文件夾、可創(chuàng)建文件、編輯文件名、可刪除等等;

渲染列表數(shù)據(jù)的時(shí)候,列表的子項(xiàng)還是列表。針對(duì)多層級(jí)的列表,我們采用tree的方式,從根節(jié)點(diǎn)一次創(chuàng)建綁定子節(jié)點(diǎn)的方式,可以遞歸式的調(diào)用本身,對(duì)我們的樹(shù)形結(jié)構(gòu)進(jìn)行展示;并且支持多余的樹(shù)形拓展;

代碼區(qū)域

1、創(chuàng)建TreeList文件夾,其中創(chuàng)建:fonts文件夾、index.js文件、tools.js文件、Tree.js文件、VueTreeList.vue文件;

2、fonts文件夾主要用來(lái)存放icon圖標(biāo)的,這里就不展示了,依據(jù)項(xiàng)目在阿里矢量圖標(biāo)內(nèi)新增,然后在VueTreeList.vue內(nèi)進(jìn)行替換

使用

源代碼地址

 <vue-tree-list
    ref="VueTreeList"
    :model="treeData" // 初識(shí)數(shù)據(jù)源,treeData: new Tree([]),
    :activeId="activeId" // 選中的id及背景色
    default-leaf-node-name="新建文件" // 默認(rèn)創(chuàng)建文件名稱(chēng)
    default-tree-node-name="新建目錄" // 默認(rèn)創(chuàng)建文件夾名稱(chēng)
    :default-expanded="isExpanded" // 默認(rèn)是否展開(kāi)文件夾
    @click="handleOnClick" // 點(diǎn)擊當(dāng)前節(jié)點(diǎn)
    @moveGraph="moveGraph" // 右側(cè)數(shù)據(jù)拖拽至當(dāng)前節(jié)點(diǎn)觸發(fā),可刪除不使用
    @add-node="handleOnAddNode" // 點(diǎn)擊創(chuàng)建節(jié)點(diǎn)
    @end-edit="handleOnChangeNameEnd" // 點(diǎn)擊編輯當(dāng)前節(jié)點(diǎn)的名稱(chēng)
    @delete-node="deleteNode" // 點(diǎn)擊刪除當(dāng)前節(jié)點(diǎn)
    @drop="handleDrop" // 拖拽上下節(jié)點(diǎn)我已注釋掉,依據(jù)需求自身放開(kāi)
    @drop-before="hadnleDropBefore" // 開(kāi)始拖拽之前的觸發(fā)函數(shù)
    @drop-after="handleDropAfter" // 結(jié)束拖拽完之后的觸發(fā)函數(shù)
    loadDataApi="/api/tree-dir" // 點(diǎn)擊左側(cè)icon,觸發(fā)遠(yuǎn)程加載填充子數(shù)據(jù)Api接口
>
</vue-tree-list>

1.1 創(chuàng)建index.js文件,也是往外暴露的入口文件;(文章并未按照思路排序)

/**
 * Created by ayou on 17/7/21.
 */
import VueTreeList from './VueTreeList'
import { Tree, TreeNode } from './Tree'
VueTreeList.install = Vue => {
  Vue.component(VueTreeList.name, VueTreeList)
}
export default VueTreeList
export { Tree, TreeNode, VueTreeList }

1.2 創(chuàng)建tools.js文件;

/**
 * Created by ayou on 18/2/6.
 */
var handlerCache
export const addHandler = function(element, type, handler) {
  handlerCache = handler
  if (element.addEventListener) {
    element.addEventListener(type, handler, false)
  } else if (element.attachEvent) {
    element.attachEvent('on' + type, handler)
  } else {
    element['on' + type] = handler
  }
}
export const removeHandler = function(element, type) {
  if (element.removeEventListener) {
    element.removeEventListener(type, handlerCache, false)
  } else if (element.detachEvent) {
    element.detachEvent('on' + type, handlerCache)
  } else {
    element['on' + type] = null
  }
}
// depth first search
export const traverseTree = (root) => {
  const { children, parent, ...newRoot } = root;
  if (children && children.length > 0) {
    newRoot.children = children.map(traverseTree);
  }
  return newRoot;
};

1.2 創(chuàng)建Tree.js文件;

import { traverseTree } from './tools'
export class TreeNode {
  constructor(data) {
    const { id, isLeaf, editNode } = data
    this.id = typeof id !== 'undefined' ? id : Math.floor(new Date().valueOf() * (Math.random() + 1))
    this.parent = null
    this.children = null
    this.isLeaf = !!isLeaf
    this.editNode = editNode || false
    for (const key in data) {
      if (key !== 'id' && key !== 'children' && key !== 'isLeaf') {
        this[key] = data[key]
      }
    }
  }
  changeName(name) {
    this.name = name
  }
  changeNodeId(id) {
    this.id = id
  }
  addChildren(children) {
    if (!this.children) {
      this.children = []
    }
    if (Array.isArray(children)) {
      children.forEach(child => {
        child.parent = this
        child.pid = this.id
      })
      this.children.push(...children)
    } else {
      const child = children
      child.parent = this
      child.pid = this.id
      this.children.push(child)
    }
  }
  // remove self
  remove() {
    const parent = this.parent
    const index = parent.children.findIndex(child => child === this)
    parent.children.splice(index, 1)
  }
  // remove child
  _removeChild(child, bool) {
    const index = this.children.findIndex(c => bool ? c.id === child.id : c === child)
    if (index !== -1) {
      this.children.splice(index, 1)
    }
  }
  isTargetChild(target) {
    let parent = target.parent
    while (parent) {
      if (parent === this) {
        return true
      }
      parent = parent.parent
    }
    return false
  }
  moveInto(target) {
    if (this.name === 'root' || this === target) {
      return
    }
    if (this.isTargetChild(target)) {
      return
    }
    if (target.isLeaf) {
      return
    }
    this.parent.removeChild(this)
    this.parent = target
    this.pid = target.id
    if (!target.children) {
      target.children = []
    }
    target.children.unshift(this)
  }
  findChildIndex(child) {
    return this.children.findIndex(c => c === child)
  }
  _canInsert(target) {
    if (this.name === 'root' || this === target) {
      return false
    }
    if (this.isTargetChild(target)) {
      return false
    }
    this.parent.removeChild(this)
    this.parent = target.parent
    this.pid = target.parent.id
    return true
  }
  insertBefore(target) {
    if (!this._canInsert(target)) return
    const pos = target.parent.findChildIndex(target)
    target.parent.children.splice(pos, 0, this)
  }
  insertAfter(target) {
    if (!this._canInsert(target)) return
    const pos = target.parent.findChildIndex(target)
    target.parent.children.splice(pos + 1, 0, this)
  }
  toString() {
    return JSON.stringify(traverseTree(this))
  }
}
export class Tree {
  constructor(data) {
    this.root = new TreeNode({ name: 'root', isLeaf: false, id: 0 })
    this.initNode(this.root, data)
    return this.root
  }
  initNode(node, data) {
    data.forEach(_data => {
      const child = new TreeNode(_data)
      if (_data.children && _data.children.length > 0) {
        this.initNode(child, _data.children)
      }
      node.addChildren(child)
    })
  }
}

1.3 創(chuàng)建VueTreeList.vue文件;

說(shuō)明:支持點(diǎn)擊創(chuàng)建遠(yuǎn)程數(shù)據(jù),loadDataAjax方法,需要自己研究功能小編已實(shí)現(xiàn);現(xiàn)有代碼基本功能已經(jīng)完善,需要依賴(lài)自己的項(xiàng)目進(jìn)行變更和更改;treeNode可以直接訪問(wèn)和修改數(shù)據(jù)源的,需要讀者自己發(fā)掘;

<template>
  <div :class="['vtl', isMobile && 'isMobile']">
    <div
      v-if="model.name !== 'root'"
      :id="model.id"
      class="vtl-node"
      :class="{ 'vtl-leaf-node': model.isLeaf, 'vtl-tree-node': !model.isLeaf }"
    >
      <div class="vtl-border vtl-up" :class="{ 'vtl-active': isDragEnterUp }" />
      <div
        :class="['vtl-node-main', { 'vtl-active': isDragEnterNode }]"
        :style="{ fontSize: '10px' }"
        @drop="drop"
        @mouseover="mouseOver"
        @mouseout="mouseOut"
        @click.stop="handleCurClick"
        @dragover="dragOver"
        @dragenter="dragEnter"
        @dragleave="dragLeave"
      >
      <span
          v-if="!model.children"
          class="vtl-caret vtl-is-small"
        >
          <i
            class="vtl-icon"
            style="cursor: pointer; width: 11px;"
          ></i>
        </span>
        <span
          v-if="model.children"
          class="vtl-caret vtl-is-small"
        >
          <i
            class="vtl-icon"
            :class="caretClass"
            style="cursor: pointer"
            @click.prevent.stop="toggle"
          ></i>
          <i
            v-if="isRemoteLoading"
            class="Custom_demo-spin-icon-load ivu-icon ivu-icon-ios-loading"
            style="font-size: 16px; margin-right: 3px; margin-top: -2px"
          ></i>
        </span>
        <span v-if="model.isLeaf">
          <slot
            name="leafNodeIcon"
            :expanded="expanded"
            :model="model"
            :root="rootNode"
          >
            <i
              style="cursor: pointer"
              class="vtl-icon vtl-menu-icon vtl-icon-file"
            ></i>
          </slot>
        </span>
        <span v-else>
          <slot
            name="treeNodeIcon"
            :expanded="expanded"
            :model="model"
            :root="rootNode"
          >
            <img
              class="custom_img"
              style="width:15px;margin-right: 3px"
              src="../../../static/img/folder.png"
              alt=""
            />
          </slot>
        </span>
        <div
          v-if="!editable"
          :class="[
            'vtl-node-content',
            isShowClickBackg,
            { custom_class_hiddle: isHover, custom_class_click: model.isLeaf }
          ]"
          :style="{
            color: model.matched ? '#D9262C' : null,
            cursor: 'pointer'
          }"
        >
          <slot
            name="leafNameDisplay"
            :expanded="expanded"
            :model="model"
            :root="rootNode"
          >
            {{ model.name }}
          </slot>
        </div>
        <input
          v-if="editable || handleInitEditable(model)"
          class="vtl-input"
          type="text"
          ref="nodeInput"
          :value="model.name"
          @input="updateName"
          @blur="setUnEditable"
          @keyup.enter="setUnEditable"
        />
        <div class="vtl-operation" v-show="isHover">
          <!-- 新增設(shè)備 -->
          <span
            title="新增設(shè)備"
            v-btn-key="rolespermiss.addDevice"
            @click.stop.prevent="createChild"
            v-if="
              (!model.isDevice || model.isDir === false) &&
                $route.path != '/autoMonitorBoard'
            "
          >
            <slot
              name="addLeafNodeIcon"
              :expanded="expanded"
              :model="model"
              :root="rootNode"
            >
              <i class="vtl-icon vtl-icon-plus"></i>
            </slot>
          </span>
          <!-- 編輯名稱(chēng) -->
          <span
            title="編輯名稱(chēng)"
            v-btn-key="rolespermiss.editFolder"
            @click.stop.prevent="setEditable(true)"
            v-if="
              !model.editNodeDisabled &&
                !model.isDevice &&
                $route.path != '/autoMonitorBoard'
            "
          >
            <slot
              name="editNodeIcon"
              :expanded="expanded"
              :model="model"
              :root="rootNode"
            >
              <i class="vtl-icon vtl-icon-edit"></i>
            </slot>
          </span>
          <!-- 刪除節(jié)點(diǎn) -->
          <span
            title="刪除節(jié)點(diǎn)"
            @click.stop.prevent="delNode"
            style="line-height: 14px;"
            v-if="$route.path != '/autoMonitorBoard'"
            v-btn-key="rolespermiss.deleteFolder"
          >
            <slot
              name="delNodeIcon"
              :expanded="expanded"
              :model="model"
              :root="rootNode"
            >
              <i class="vtl-icon vtl-icon-trash"></i>
            </slot>
          </span>
          <!-- 創(chuàng)建子目錄 -->
          <span
            :title="defaultAddTreeNodeTitle"
            @click.stop.prevent="addChild(false)"
            v-btn-key="rolespermiss.createFolder"
            v-if="
              !model.addTreeNodeDisabled &&
                !model.isLeaf &&
                !model.isDevice &&
                $route.path != '/autoMonitorBoard'
            "
          >
            <slot
              name="addTreeNodeIcon"
              :expanded="expanded"
              :model="model"
              :root="rootNode"
            >
              <i class="vtl-icon vtl-icon-folder-plus-e"></i>
            </slot>
          </span>
          <!-- 詳情按鈕 -->
          <span
            title="設(shè)備詳情"
            style="margin-top: -1px"
            @click.stop="handleViewDetail"
            v-btn-key="rolespermiss.folderDetail"
            v-if="!model.addTreeNodeDisabled && model.isLeaf && !model.isDevice"
          >
            <Icon style="color: #d9262c" type="ios-paper-outline" />
          </span>
        </div>
      </div>
      <div
        v-if="
          model.children &&
            model.children.length > 0 &&
            (expanded || model.expanded)
        "
        class="vtl-border vtl-bottom"
        :class="{ 'vtl-active': isDragEnterBottom }"
      ></div>
    </div>
    <div
      :class="{ 'vtl-tree-margin': model.name !== 'root' }"
      v-if="isFolder && (model.name === 'root' || expanded || model.expanded)"
    >
      <item
        :model="model"
        :title="model.name"
        v-for="model in model.children"
        :key="model.id"
        :activeId="activeId"
        :loadDataApi="loadDataApi"
        :rolespermiss="rolespermiss"
        :requestHeader="requestHeader"
        :default-tree-node-name="defaultTreeNodeName"
        :default-leaf-node-name="defaultLeafNodeName"
        :default-expanded="defaultExpanded"
      >
        <template v-slot:leafNameDisplay="slotProps">
          <slot name="leafNameDisplay" v-bind="slotProps" />
        </template>
        <template v-slot:addTreeNodeIcon="slotProps">
          <slot name="addTreeNodeIcon" v-bind="slotProps" />
        </template>
        <template v-slot:addLeafNodeIcon="slotProps">
          <slot name="addLeafNodeIcon" v-bind="slotProps" />
        </template>
        <template v-slot:editNodeIcon="slotProps">
          <slot name="editNodeIcon" v-bind="slotProps" />
        </template>
        <template v-slot:delNodeIcon="slotProps">
          <slot name="delNodeIcon" v-bind="slotProps" />
        </template>
        <template v-slot:leafNodeIcon="slotProps">
          <slot name="leafNodeIcon" v-bind="slotProps" />
        </template>
        <template v-slot:treeNodeIcon="slotProps">
          <slot name="treeNodeIcon" v-bind="slotProps" />
        </template>
      </item>
    </div>
  </div>
</template>
<script>
import { request } from "@/axios/index";
import { TreeNode } from "./Tree.js";
import { removeHandler } from "./tools.js";
import { isShowMobile } from "@/storage/storeutil";
let compInOperation = null;
export default {
  name: "vue-tree-list",
  props: {
    model: {
      type: Object
    },
    activeId: Number,
    rolespermiss: Object,
    loadDataApi: String,
    requestHeader: Object,
    defaultLeafNodeName: {
      type: String,
      default: "新建"
    },
    defaultTreeNodeName: {
      type: String,
      default: "新建"
    },
    defaultAddTreeNodeTitle: {
      type: String,
      default: "新建"
    },
    defaultExpanded: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      isHover: false,
      editable: false,
      isDragEnterUp: false,
      isDragEnterBottom: false,
      isDragEnterNode: false,
      isRemoteLoading: false,
      expanded: this.defaultExpanded,
      clickEditIcon: false
    };
  },
  computed: {
    rootNode() {
      var node = this.$parent;
      while (node._props.model.name !== "root") {
        node = node.$parent;
      }
      return node;
    },
    caretClass() {
      return this.model.expanded
        ? "vtl-icon-caret-down"
        : this.expanded
        ? "vtl-icon-caret-down"
        : "vtl-icon-caret-right";
    },
    isFolder() {
      return this.model.children && this.model.children.length;
    },
    isShowClickBackg() {
      const {
        model: { id }
      } = this;
      return { activeItem: id === this.activeId };
    },
    isMobile() {
      return isShowMobile();
    }
    // treeNodeClass() {
    //   const {
    //     model: { dragDisabled, disabled },
    //   } = this;
    //   return {
    //     "vtl-drag-disabled": dragDisabled,
    //     "vtl-disabled": disabled,
    //   };
    // },
  },
  methods: {
    updateName(e) {
      var oldName = this.model.name;
      this.model.changeName(e.target.value);
      this.rootNode.$emit("change-name", {
        id: this.model.id,
        oldName: oldName,
        newName: e.target.value,
        node: this.model
      });
    },
    // 點(diǎn)擊左側(cè)箭頭異步加載子節(jié)點(diǎn)數(shù)據(jù)
    toggle() {
      if (this.model.expanded) {
        this.expanded = false;
      } else {
        this.expanded = !this.expanded;
      }
      this.model.expanded = false;
    },
    // 刪除節(jié)點(diǎn)
    delNode() {
      this.rootNode.$emit("delete-node", this.model);
    },
    setEditable(bool) {
      this.clickEditIcon = bool || false;
      this.editable = true;
      this.$nextTick(() => {
        const $input = this.$refs.nodeInput;
        $input.focus();
        this.handleCurClick();
      });
    },
    setUnEditable(e) {
      if (this.editable === false) return;
      this.editable = false;
      this.model.editNode = false;
      var oldName = this.model.name;
      this.model.changeName(e.target.value);
      this.rootNode.$emit(
        "change-name",
        {
          id: this.model.id,
          oldName: oldName,
          newName: e.target.value,
          eventType: "blur"
        },
        this.model
      );
      this.rootNode.$emit(
        "end-edit",
        {
          id: this.model.id,
          oldName: oldName,
          newName: e.target.value
        },
        this.model,
        this.clickEditIcon
      );
      this.clickEditIcon = false;
    },
    // 新建目錄
    handleInitEditable(row) {
      if (row.editNode) {
        this.setEditable();
      }
    },
    // 異步請(qǐng)求數(shù)據(jù)
    async loadDataAjax(Refresh) {
      if (Refresh) {
        this.model.isLeaf = true;
      }
      const { method, params, httpApi } = this.requestHeader || {};
      const httpUrl = this.model.isLeaf ? httpApi : this.loadDataApi;
      const requestParams = this.model.isLeaf
        ? { treeDirId: this.model.id, ...(params || {}) }
        : { id: this.model.id, ...(params || {}) };
      try {
        this.isRemoteLoading = true;
        const { code, data, message } = await request(
          method || "GET",
          httpUrl,
          requestParams
        );
        if (code !== 0) {
          return (
            (this.expanded = false),
            (this.isRemoteLoading = false),
            this.$Message.error("失敗," + message || "請(qǐng)求失敗")
          );
        }
        const dataSource = this.model.isLeaf ? data.deviceList : data.data;
        if (!dataSource) {
          return (this.expanded = false), (this.isRemoteLoading = false);
        }
        if (Array.isArray(dataSource) && dataSource.length) {
          dataSource.forEach(item => {
            const node = new TreeNode(item);
            if (Refresh && this.expanded) {
              this.model._removeChild(node, true);
            }
            this.model.addChildren(node, true);
          });
          this.expanded = true;
        }
        this.isRemoteLoading = false;
      } catch (err) {
        this.expanded = false;
        this.isRemoteLoading = false;
        throw new Error(err);
      }
    },
    mouseOver() {
      if (this.model.disabled) return;
      this.isHover = true;
    },
    mouseOut() {
      this.isHover = false;
    },
    // 點(diǎn)擊當(dāng)前節(jié)點(diǎn)
    handleCurClick() {
      this.rootNode.$emit(
        "click",
        {
          toggle: this.toggle,
          ...this.model
        },
        this.editable
      );
      if (this.$route.path=='/autoMonitorBoard') {
        this.toggle()
      }
    },
    // 查看詳情
    handleViewDetail() {
      this.rootNode.$emit("viewDetail", {
        ...this.model
      });
    },
    // 新增子節(jié)點(diǎn)
    async addChild(isLeaf) {
      if (!this.expanded) {
        await this.loadDataAjax();
        this.handleAddChildren(isLeaf);
      } else {
        this.handleAddChildren(isLeaf);
      }
    },
    handleAddChildren(isLeaf) {
      const name = isLeaf ? this.defaultLeafNodeName : this.defaultTreeNodeName;
      this.expanded = true;
      var node = new TreeNode({ name, isLeaf, isDir: false });
      this.model.addChildren(node, true);
      this.rootNode.$emit("add-node", node);
    },
    createChild() {
      this.rootNode.$emit("create-child", {
        ...this.model,
        loadDataAjax: this.loadDataAjax
      });
    },
    // dragStart(e) {
    //   if (!(this.model.dragDisabled || this.model.disabled)) {
    //     compInOperation = this;
    //     e.dataTransfer.setData("data", "data");
    //     e.dataTransfer.effectAllowed = "move";
    //     return true;
    //   }
    //   return false;
    // },
    // dragEnd() {
    //   compInOperation = null;
    // },
    dragOver(e) {
      e.preventDefault();
      return true;
    },
    dragEnter(ev) {
      this.isDragEnterNode = true;
    },
    dragLeave() {
      this.isDragEnterNode = false;
    },
    drop(ev) {
      if (ev.dataTransfer && ev.dataTransfer.getData("data")) {
        const data = JSON.parse(ev.dataTransfer.getData("data"));
        this.isDragEnterNode = false;
        this.$Modal.confirm({
          title: "提示",
          content: `是否確定要移入【${this.model.title}】目錄中?`,
          closable: true,
          maskClosable: true,
          onOk: () => {
            this.axios
              .request("POST", "/api/move", {
                id: data.id,
                treeDirId: this.model.id
              })
              .then(response => {
                if (+response.code === 0) {
                  this.$Message.success("移動(dòng)成功!");
                  this.rootNode.$emit("moveGraph");
                } else {
                  // 提示錯(cuò)誤
                  this.$Notice.error({
                    title: "查詢失敗",
                    desc: response.message || "請(qǐng)求失敗",
                    duration: 5
                  });
                }
              });
          }
        });
        return;
      }
      if (!compInOperation) return;
      const oldParent = compInOperation.model.parent;
      compInOperation.model.moveInto(this.model);
      this.isDragEnterNode = false;
      this.rootNode.$emit("drop", {
        target: this.model,
        node: compInOperation.model,
        src: oldParent
      });
    }
    //   dragEnterUp() {
    //     if (!compInOperation) return;
    //     this.isDragEnterUp = true;
    //   },
    //   dragOverUp(e) {
    //     e.preventDefault();
    //     return true;
    //   },
    //   dragLeaveUp() {
    //     if (!compInOperation) return;
    //     this.isDragEnterUp = false;
    //   },
    //   dropBefore() {
    //     if (!compInOperation) return;
    //     const oldParent = compInOperation.model.parent;
    //     compInOperation.model.insertBefore(this.model);
    //     this.isDragEnterUp = false;
    //     this.rootNode.$emit("drop-before", {
    //       target: this.model,
    //       node: compInOperation.model,
    //       src: oldParent,
    //     });
    //   },
    //   dragEnterBottom() {
    //     if (!compInOperation) return;
    //     this.isDragEnterBottom = true;
    //   },
    //   dragOverBottom(e) {
    //     e.preventDefault();
    //     return true;
    //   },
    //   dragLeaveBottom() {
    //     if (!compInOperation) return;
    //     this.isDragEnterBottom = false;
    //   },
    //   dropAfter() {
    //     if (!compInOperation) return;
    //     const oldParent = compInOperation.model.parent;
    //     compInOperation.model.insertAfter(this.model);
    //     this.isDragEnterBottom = false;
    //     this.rootNode.$emit("drop-after", {
    //       target: this.model,
    //       node: compInOperation.model,
    //       src: oldParent,
    //     });
    //   },
  },
  beforeCreate() {
    this.$options.components.item = require("./VueTreeList").default;
  },
  beforeDestroy() {
    removeHandler(window, "keyup");
  }
};
</script>
<style lang="less">
@font-face {
  font-family: "icomoon";
  src: url("fonts/icomoon.eot?ui1hbx");
  src: url("fonts/icomoon.eot?ui1hbx#iefix") format("embedded-opentype"),
    url("fonts/icomoon.ttf?ui1hbx") format("truetype"),
    url("fonts/icomoon.woff?ui1hbx") format("woff"),
    url("fonts/icomoon.svg?ui1hbx#icomoon") format("svg");
  font-weight: normal;
  font-style: normal;
}
.vtl-icon {
  font-family: "icomoon" !important;
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  &.vtl-menu-icon {
    margin-right: 4px;
    &:hover {
      color: inherit;
    }
  }
  &:hover {
    color: #d9262c;
  }
}
.vtl-icon-file:before {
  content: "\e906";
}
.vtl-icon-folder:before {
  content: "\e907";
}
.vtl-icon-caret-down:before {
  font-size: 16px;
  content: "\e901";
}
.vtl-icon-caret-right:before {
  font-size: 16px;
  content: "\e900";
}
.vtl-icon-edit:before {
  content: "\e902";
  font-size: 18px;
}
.vtl-icon-folder-plus-e:before {
  content: "\e903";
}
.vtl-icon-plus:before {
  content: "\e904";
  font-size: 16px;
}
.vtl-icon-trash:before {
  content: "\e905";
}
.vtl {
  cursor: default;
  margin-left: -3px;
}
.vtl-border {
  height: 5px;
  &.vtl-up {
    margin-top: -5px;
    background-color: transparent;
  }
  &.vtl-bottom {
    background-color: transparent;
  }
  &.vtl-active {
    border-bottom: 2px dashed pink;
  }
}
.vtl-node-main {
  display: flex;
  align-items: center;
  margin: 2.5px auto 2.5px -1px;
  .vtl-input {
    border: none;
    min-width: 200px;
    border-bottom: 1px solid blue;
  }
  &:hover {
    background-color: #f0f0f0;
  }
  &.vtl-active {
    outline: 1.5px dashed #d9262c;
  }
  .vtl-operation {
    display: flex;
    margin-left: 1rem;
    height: 18px;
    letter-spacing: 1px;
    span {
      margin-right: 10px;
    }
    .vtl-icon {
      color: #d9262c;
      vertical-align: sub;
    }
  }
}
.vtl-node-content {
  white-space: nowrap;
  padding: 1px 0px;
}
.activeItem {
  background: #ccc;
}
.custom_class_click {
  cursor: pointer;
}
.custom_class_hiddle {
  overflow: hidden;
  text-overflow: ellipsis;
}
.vtl-item {
  cursor: pointer;
}
.vtl-tree-margin {
  margin-left: 2em;
}
.Custom_demo-spin-icon-load {
  font-size: 18px;
  color: #d9262c;
  animation: ani-demo-spin 1s linear infinite;
}
@keyframes ani-demo-spin {
  from {
    transform: rotate(0deg);
  }
  50% {
    transform: rotate(180deg);
  }
  to {
    transform: rotate(360deg);
  }
}
.demo-spin-col {
  height: 100px;
  position: relative;
  border: 1px solid #eee;
}
.vtl-caret {
  display: flex;
  .vtl-icon {
    width: 28px;
    text-align: right;
  }
}
.isMobile {
  .vtl {
    margin-left: 3px;
  }
  .vtl-node-content {
    white-space: nowrap;
    padding: 1px 0px;
    font-size: 2.6em;
  }
  .custom_img {
    width: 2.5em !important;
  }
  .vtl-icon-caret-down:before,
  .vtl-icon-caret-right:before,
  .vtl-icon-plus:before,
  .vtl-icon-edit:before,
  .vtl-icon-trash:before,
  .vtl-icon-folder-plus-e:before {
    font-size: 30px;
  }
  .vtl-node-main .vtl-operation {
    height: auto;
  }
}
</style>

到此這篇關(guān)于vue實(shí)現(xiàn)自定義樹(shù)形組件的文章就介紹到這了,更多相關(guān)vue自定義樹(shù)形組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue如何使用watch監(jiān)聽(tīng)指定數(shù)據(jù)的變化

    vue如何使用watch監(jiān)聽(tīng)指定數(shù)據(jù)的變化

    這篇文章主要介紹了vue如何使用watch監(jiān)聽(tīng)指定數(shù)據(jù)的變化,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue 動(dòng)態(tài)添加表單實(shí)現(xiàn)動(dòng)態(tài)雙向綁定

    Vue 動(dòng)態(tài)添加表單實(shí)現(xiàn)動(dòng)態(tài)雙向綁定

    動(dòng)態(tài)表單是一個(gè)常見(jiàn)的需求,本文詳細(xì)介紹了Vue.js中實(shí)現(xiàn)動(dòng)態(tài)表單的創(chuàng)建,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-12-12
  • Vue.js響應(yīng)式數(shù)據(jù)的簡(jiǎn)單實(shí)現(xiàn)方法(一看就會(huì))

    Vue.js響應(yīng)式數(shù)據(jù)的簡(jiǎn)單實(shí)現(xiàn)方法(一看就會(huì))

    Vue最巧妙的特性之一是其響應(yīng)式系統(tǒng),下面這篇文章主要給大家介紹了關(guān)于Vue.js響應(yīng)式數(shù)據(jù)的簡(jiǎn)單實(shí)現(xiàn)方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-03-03
  • vue打包后出現(xiàn)空白頁(yè)的原因及解決方式詳解

    vue打包后出現(xiàn)空白頁(yè)的原因及解決方式詳解

    在項(xiàng)目中很多時(shí)候需要用到vue打包成html不需要放在服務(wù)器上就能瀏覽,根據(jù)官網(wǎng)打包出來(lái)的html直接打開(kāi)是顯示空白,下面這篇文章主要給大家介紹了關(guān)于vue打包后出現(xiàn)空白頁(yè)的原因及解決方式的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • VUE中v-model和v-for指令詳解

    VUE中v-model和v-for指令詳解

    本篇文章主要介紹了VUE中v-model和v-for指令詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • Vue3計(jì)算屬性computed和監(jiān)聽(tīng)屬性watch區(qū)別解析

    Vue3計(jì)算屬性computed和監(jiān)聽(tīng)屬性watch區(qū)別解析

    計(jì)算屬性適用于對(duì)已有的數(shù)據(jù)進(jìn)行計(jì)算,派生新的數(shù)據(jù),并在模板中使用;而監(jiān)聽(tīng)屬性適用于監(jiān)聽(tīng)數(shù)據(jù)的變化,并執(zhí)行一些特定的操作,根據(jù)具體的需求和場(chǎng)景,選擇適合的機(jī)制這篇文章主要介紹了Vue3計(jì)算屬性computed和監(jiān)聽(tīng)屬性watch,需要的朋友可以參考下
    2024-02-02
  • vue.js實(shí)現(xiàn)選項(xiàng)卡切換

    vue.js實(shí)現(xiàn)選項(xiàng)卡切換

    這篇文章主要為大家詳細(xì)介紹了vue.js實(shí)現(xiàn)選項(xiàng)卡切換功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • vue后端傳文件流轉(zhuǎn)化成blob對(duì)象,前端點(diǎn)擊下載返回undefined問(wèn)題

    vue后端傳文件流轉(zhuǎn)化成blob對(duì)象,前端點(diǎn)擊下載返回undefined問(wèn)題

    這篇文章主要介紹了vue后端傳文件流轉(zhuǎn)化成blob對(duì)象,前端點(diǎn)擊下載返回undefined問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • vue項(xiàng)目中$t()的意思是什么

    vue項(xiàng)目中$t()的意思是什么

    這篇文章主要介紹了vue項(xiàng)目中$t()的意思是什么,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vite+Vue3使用MockJS的實(shí)現(xiàn)示例

    Vite+Vue3使用MockJS的實(shí)現(xiàn)示例

    寫(xiě)一些純前端的項(xiàng)目時(shí),自己造數(shù)據(jù)有些麻煩,于是我們可以利用mock造一些簡(jiǎn)單的數(shù)據(jù),來(lái)滿足我們的需求,本文主要介紹了Vite+Vue3使用MockJS的實(shí)現(xiàn)示例,感興趣的可以了解一下
    2024-01-01

最新評(píng)論