zoukankan      html  css  js  c++  java
  • vue可拖拽树

     注:自用,一些样式其他人可能没有

    <!-- Vue SFC -->
    <template>
      <div class="container bxs">
        <div class="ct-inner bxs">
          <div class="ct-inner-fiexd w">
            <el-input placeholder="请输入关键词" suffix-icon="el-icon-search" v-model="filterText"></el-input>
            <div class="w clearfix tc mt10">
              <el-button class="fll" type="primary" plain size="mini">刷新</el-button>
              <el-button type="primary" plain size="mini" @click="unFoldAll">全部展开</el-button>
              <el-button class="flr" type="primary" plain size="mini" @click="collapseAll">全部收起</el-button>
            </div>
          </div>
          <div class="ct-inner-content h">
            <!-- show-checkbox 是否展示多选框 -->
            <!-- :check-on-click-node="true" 点击文本内容是否选中 -->
            <el-tree
              v-if="openOrNot"
              :data="treeData"
              node-key="id"
              :default-expand-all="defaultExpand"
              :expand-on-click-node="false"
              @node-click="handleLeftclick"
              @node-drag-start="handleDragStart"
              @node-drag-enter="handleDragEnter"
              @node-drag-leave="handleDragLeave"
              @node-drag-over="handleDragOver"
              @node-drag-end="handleDragEnd"
              @node-drop="handleDrop"
              @node-contextmenu="rightClick"
              :filter-node-method="filterNode"
              draggable
              :allow-drop="allowDrop"
              :allow-drag="allowDrag"
              ref="tree"
            >
              <span class="slot-t-node span-ellipsis" slot-scope="{ node, data }">
                <span class="span-ellipsis-inner" v-show="!data.isEdit">
                  <!-- <el-tooltip class="item" effect="dark" :content="node.label" placement="right"> -->
                  <span class="span-ellipsis">
                    <span
                      class="span-ellipsis"
                      :class="[(selectTreeData&&data.id==selectTreeData.id)? 'slot-t-node--label' : '']"
                      style="vertical-align:middle;"
                    >
                      <i class="iconfont jxintegral-fill"></i>
                      {{node.label}}
                    </span>
                  </span>
                  <!-- </el-tooltip> -->
                </span>
                <!-- autofocus -->
                <span v-show="data.isEdit">
                  <el-input
                    class="slot-t-input"
                    style="height:28px;"
                    size="mini"
                    v-model="data.label"
                    :ref="'slotTreeInput'+data.id"
                    @blur.stop="NodeBlur(node,data)"
                    @keydown.native.enter="NodeBlur(node,data)"
                  ></el-input>
                </span>
              </span>
            </el-tree>
    
            <el-card class="box-card" ref="card" v-show="menuVisible">
              <div @click="addSameLevelNode()" v-show="firstLevel">
                <i class="el-icon-circle-plus-outline"></i>
                <span class="ml10">同级增加</span>
              </div>
    
              <div class="add" @click="addChildNode()">
                <i class="el-icon-circle-plus-outline"></i>
                <span class="ml10">子级增加</span>
              </div>
    
              <div class="delete" @click="deleteNode()">
                <i class="el-icon-remove-outline"></i>
                <span class="ml10">删除节点</span>
              </div>
    
              <div class="edit" @click="editNode()">
                <i class="el-icon-edit"></i>
                <span class="ml10">修改节点</span>
              </div>
            </el-card>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    import axios from "axios";
    export default {
      name: "PersonManageLf",
      components: {},
      data() {
        return {
          openOrNot: true, //展开收缩dom挂载切换
          defaultExpand: true, //默认全部展开
          eleId: "",
    
          isShow: false,
    
          currentData: "",
    
          currentNode: "",
    
          menuVisible: false,
    
          firstLevel: false,
    
          filterText: "",
    
          maxexpandId: 4,
    
          treeData: [
            {
              id: 1,
    
              label: "一级 1",
    
              isEdit: false,
    
              children: [
                {
                  id: 4,
    
                  label: "二级 1-1",
    
                  isEdit: false,
    
                  children: [
                    {
                      id: 9,
    
                      label:
                        "三级 1-1-1呜呜呜呜呜呜呜呜无无无无无无无无无无无无无无无无无",
    
                      isEdit: false,
                    },
                    {
                      id: 10,
    
                      label: "三级 1-1-2",
    
                      isEdit: false,
                    },
                  ],
                },
              ],
            },
            {
              id: 2,
    
              label: "一级 2",
    
              isEdit: false,
    
              children: [
                {
                  id: 5,
    
                  label: "二级 2-1",
    
                  isEdit: false,
                },
                {
                  id: 6,
    
                  label: "二级 2-2",
    
                  isEdit: false,
                },
              ],
            },
            {
              id: 3,
    
              label: "一级 3",
    
              isEdit: false,
    
              children: [
                {
                  id: 7,
    
                  label: "二级 3-1",
    
                  isEdit: false,
                },
                {
                  id: 8,
    
                  label: "二级 3-2",
    
                  isEdit: false,
    
                  children: [
                    {
                      id: 11,
    
                      label: "三级 3-2-1",
    
                      isEdit: false,
                    },
                    {
                      id: 12,
    
                      label: "三级 3-2-2",
    
                      isEdit: false,
                    },
                    {
                      id: 13,
    
                      label: "三级 3-2-3",
    
                      isEdit: false,
                    },
                  ],
                },
              ],
            },
          ],
          treeDataCopy: "", //   拖拽结束后验证后不可拖拽
          defaultProps: {
            children: "children",
    
            label: "label",
          },
          selectTreeNode: "", //选中的树节点,内含父节点
          selectTreeData: "", //选中的树data
          newAddTreeObjs: {}, //新增节点储存对象
          nowAddTreeNodeid: "", //当前新增节点id
        };
      },
      methods: {
        // 全部展开
        unFoldAll() {
          let self = this;
          // 将没有转换成树的原数据
          let list = this.treeData;
          for (let i = 0; i < list.length; i++) {
            // 将没有转换成树的原数据设置key为... 的展开
            self.$refs.tree.store.nodesMap[list[i].id].expanded = true;
          }
        },
        // 全部折叠
        collapseAll() {
          let self = this;
          // 将没有转换成树的原数据
          let list = this.treeData;
          for (let i = 0; i < list.length; i++) {
            self.$refs.tree.store.nodesMap[list[i].id].expanded = false;
          }
        },
        renderContent(h, { node, data, store }) {
          console.log(node.label);
          console.log(data);
          console.log(store);
          return (
            <div style="display:inline-block;">
              <span style="">{node.label}</span>
            </div>
          );
        },
        open() {
          this.defaultExpand = !this.defaultExpand;
          this.openOrNot = false;
          setTimeout(() => {
            this.openOrNot = true;
          }, 10);
        },
    
        NodeBlur(Node, data) {
          // debugger;
    
          console.log(Node, data);
    
          if (data.label.length === 0) {
            this.$message.error("菜单名不可为空!");
            return false;
          } else {
            if (data.isEdit) {
              this.$set(data, "isEdit", false);
              console.log(data.isEdit);
            }
            this.$nextTick(() => {
              this.$refs["slotTreeInput" + data.id].$refs.input.focus();
            });
          }
        },
    
        // 查询
    
        filterNode(value, data) {
          if (!value) return true;
    
          return data.label.indexOf(value) !== -1;
        },
    
        handleDragStart(node, ev) {
          console.log(this.treeData, "");
          console.log("drag start", node);
          //   如果要阻止拖拽
          //   if(node.childNodes.length>0){
          //       console.log("有子节点不能移动")
          //       ev.preventDefault();
          //       return;
          //   }
        },
    
        handleDragEnter(draggingNode, dropNode, ev) {
          console.log("tree drag enter: ", dropNode.label);
        },
    
        handleDragLeave(draggingNode, dropNode, ev) {
          console.log("tree drag leave: ", dropNode.label);
        },
    
        handleDragOver(draggingNode, dropNode, ev) {
          console.log("tree drag over: ", dropNode.label);
        },
    
        handleDragEnd(draggingNode, dropNode, dropType, ev) {
          console.log("tree drag end: ", dropNode && dropNode.label, dropType);
        },
    
        handleDrop(draggingNode, dropNode, dropType, ev) {
          console.log("tree drop: ", dropNode.label, dropType);
          //   拖拽结束后验证后不可拖拽
          //    console.log(this.treeData,'树')
          //    this.treeData=JSON.parse(JSON.stringify(this.treeDataCopy));
        },
    
        allowDrop(draggingNode, dropNode, type) {
          console.log(dropNode.data)
          if (dropNode.data.label === "二级 3-1") {
            return type !== "inner";
          } else {
            return true;
          }
        },
    
        allowDrag(draggingNode) {
          return draggingNode.data.label.indexOf("三级 3-2-2") === -1;
        },
    
        // 鼠标右击事件
    
        rightClick(MouseEvent, object, Node, element) {
          //   debugger;
          console.log(Node);
    
          this.currentData = object;
    
          this.currentNode = Node;
    
          if (Node.level === 1) {
            this.firstLevel = true;
          } else {
            this.firstLevel = false;
          }
    
          this.menuVisible = true; // let menu = document.querySelector('#card')
    
          // /* 菜单定位基于鼠标点击位置 */
    
          // menu.style.left = event.clientX + 'px'
    
          // menu.style.top = event.clientY + 'px'
    
          document.addEventListener("click", this.foo);
    
          // console.log(event.clientY);
          this.$refs.card.$el.style.left = event.clientX + 40 - 250 + "px";
    
          this.$refs.card.$el.style.top = event.clientY + 10 - 165 + "px";
        },
    
        // 鼠标左击事件
    
        handleLeftclick(data, node) {
          // console.log(data,'选中的节点')
          this.selectTreeNode = node;
          this.selectTreeData = data;
          this.foo(data.id, true);
        },
        //判断是否为新增id,且新增id是否为真id
        sureNewOrOld(id) {
          //1 表明是旧id,2表示新id,3表示id未返回
          id = id + "";
          let arrs = id.split("-");
          let newAddTreeObjs = this.newAddTreeObjs;
          if (arrs[0] == "xzjd") {
            console.log(id);
            console.log(newAddTreeObjs);
            console.log(newAddTreeObjs[id]);
            let idData = newAddTreeObjs[id];
            if (idData.id != id) {
              return 2;
            } else {
              // 新增部门,请刷新列表获取信息!
              this.$message.warning("新增部门,请稍后操作!");
              this.selectTreeNode = "";
              this.selectTreeData = "";
              return 3;
            }
          } else {
            return 1;
          }
        },
    
        //  取消鼠标监听事件 菜单栏
    
        foo(id, havesure) {
          // havesure判断是否为左键点击
          let newAddTreeObjs = this.newAddTreeObjs;
          this.menuVisible = false; //  要及时关掉监听,不关掉的是一个坑,不信你试试,虽然前台显示的时候没有啥毛病,加一个alert你就知道了
          document.removeEventListener("click", this.foo);
          if (this.nowAddTreeNodeid) {
            this.nowAddTreeNodeid = "";
            return;
          }
          console.log("真正选中的节点");
          if (!havesure) {
            return;
          }
          let oldSure = this.sureNewOrOld(id);
          console.log(oldSure);
          if (oldSure == 2) {
          } else if (oldSure == 3) {
            return;
          } else {
            this.changeRightMess(id);
          }
          console.log();
        },
        // 刷新右侧信息
        changeRightMess(id) {
          this.$emit("sentFather", { id: id });
        },
    
        // 增加同级节点事件
    
        addSameLevelNode() {
          let id = Math.ceil(Math.random() * 1000);
          let timestamp = Date.parse(new Date());
          id = "xzjd-" + id + "-" + timestamp;
          console.log(id);
          var data = { id: id, label: "新增节点" };
          this.newAddTreeObjs[id] = data;
          this.nowAddTreeNodeid = id;
          this.$refs.tree.append(data, this.currentNode.parent);
        },
    
        // 增加子级节点事件
    
        addChildNode() {
          console.log(this.currentData);
          console.log(this.currentNode);
          // if (this.currentNode.level >= 3) {
          //   this.$message.error("最多只支持三级!");
          //   return false;
          // }
          let id = Math.ceil(Math.random() * 1000);
          let timestamp = Date.parse(new Date());
          id = "xzjd-" + id + "-" + timestamp;
          var data = { id: id, label: "新增节点" };
          this.newAddTreeObjs[id] = data;
          this.nowAddTreeNodeid = id;
          this.$refs.tree.append(data, this.currentNode);
        },
    
        // 删除节点
    
        deleteNode() {
          this.$refs.tree.remove(this.currentNode);
        },
    
        // 编辑节点
    
        editNode() {
          // debugger;
    
          if (!this.currentData.isEdit) {
            this.$set(this.currentData, "isEdit", true);
          }
        },
      },
    
      watch: {
        filterText(val) {
          this.$refs.tree.filter(val);
        },
      },
    
      mounted() {
        // this.test();
        //   拖拽结束后验证后不可拖拽
        // this.treeDataCopy=JSON.parse(JSON.stringify(this.treeData))
      },
    };
    </script>
    <style lang="scss"  scoped>
    .container {
      height: 95%;
      .ct-inner {
        height: 100%;
        position: relative;
        padding-top: 84px;
        .ct-inner-fiexd {
          position: absolute;
          left: 0;
          top: 0;
        }
        .ct-inner-content {
          // overflow: hidden;
            .text {
            font-size: 14px;
          }
          .add {
            cursor: pointer;
            margin-top: 10px;
          }
    
          .delete {
            margin: 10px 0;
            cursor: pointer;
          }
    
          .edit {
            margin-bottom: 10px;
    
            cursor: pointer;
          }
    
          .box-card {
            width: 140px;
    
            position: absolute;
    
            z-index: 1000;
          }
          .slot-t-node--label {
            background-color: #f5f7fa;
          }
        }
      }
    }
    .span-ellipsis {
      width: 100%;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      display: inline-block;
    }
    </style>
    <style >
    .el-tree {
      width: 100%;
      max-height: 95%;
      padding-bottom: 20px;
      overflow: auto;
    }
    .el-tree > .el-tree-node {
      display: inline-block;
      min-width: 100%;
    }
    .el-tree-node__content {
      height: 30px;
    }
    </style>
  • 相关阅读:
    vue.js环境的搭建
    图片上传简单demo及springboot上传图片
    mybatise 模糊查询
    thymeleaf th:onclick 传参
    thymeleaf的特殊属性赋值
    无限分类的设计及前后台代码
    mysql 多个属性排序查询
    java添加对象成功后想知道当前添加对象的id
    SpringBoot2.x集成MQTT实现消息推送
    linux下安装MQTT服务器
  • 原文地址:https://www.cnblogs.com/dianzan/p/13397389.html
Copyright © 2011-2022 走看看