h5的draggable属性实现拖拽Tree组件

本文介绍了一种在前端开发中实现可拖拽树形组件的方法,通过在树节点中添加draggable属性,使节点支持拖拽。并在拖拽过程中,通过dragstart和drop方法获取原节点和目标节点,实现节点的重新排序或移动。
1.通过在render中给每个树节点添加domProps属性,使节点支持拖拽效果,也可以选择在父组件传入draggable属性控制树是否可拖拽
domProps: {
            draggable: this.draggable
          },

2.dragstart方法获取到原节点和它的父节点,drop方法获取目标节点,将原节点从父节点删除并添加到目标节点children中

<template>
  <div>
    <Tree ref="tree" :data="data" :render="renderContent">
    </Tree>
  </div>
</template>
<script type="text/ecmascript-6">
  export default {
    name: 'dragTree',
    props: {
      data: {
        type: Array,
        default() {
          return [];
        }
      },
      draggable: {
        type: Boolean,
        default: true
      },
      showCheckbox: {
        type: Boolean,
        default: false
      },
    },
    data() {
      return {
        currentNode: {},
        parentNode: {},
        dragNode: {},
        dropNode: {},
        isChild: false,
        treeData: [],
        filterTreeData: [{
          title: '全选',
          expand: true,
          classCode: '',
          children: []
        }],
      }
    },
    methods: {
      renderContent(h, {root, node, data}) {
        data.selected = data.title === this.currentNode.title;
        return h('span', {
          domProps: {
            draggable: this.draggable
          },
          style: {
            display: 'inline-block'
          },
          class: {'node-selected': data.selected},
          on: {
            click: () => {
              this.handleSelect(root, node, data);
            },
            //拖拽开始,获取拖拽元素和拖拽元素的父节点
            dragstart: (e) => {
              e.stopPropagation();
              this.currentNode = data;
              this.dragNode = data;
              this.parentNode = root[node.parent].node;
              // this.parentNode = this.getParentNode(data.parentCode, this.data);
            },
            //把拖拽元素从父节点中删除
            dragend: (e) => {
              e.preventDefault();
            },
            //源对象在悬停在目标对象上时
            //阻止默认行为,使得drop可以触发
            dragover: (e) => {
              e.preventDefault();
            },
            //把拖拽元素从原节点上删除,并添加到目标对象上
            drop: (e) => {
              e.preventDefault();
              e.stopPropagation();
              this.dropNode = data;
              let isChild = this.isChildNode (this.dropNode, this.dragNode);
              if (!isChild) {
                let index = this.parentNode.children.indexOf(this.dragNode);
                this.parentNode.children.splice(index, 1);
                let children = this.dropNode.children || [];
                children.push(this.dragNode);
              }
            }
          }
        }, [
          h('span', [
            h('Icon', {
              props: {
                type: data.expand ?  'mt-folder-open' : 'md-folder'
              },
              style: {
                marginRight: '8px',
                color: '#2d8cf0',
                fontSize: '16px'
              }
            }),
            h('span', data.title)
          ])
        ])
      },
      /**
       * 判断目标节点是否是拖拽节点的子节点
       * @param dropNode 目标节点
       * @param dragNode 拖拽节点
       */
      isChildNode (dropNode, dragNode) {
        if (dragNode.children) {
          dragNode = dragNode.children;
          for(let i = 0; i < dragNode.length; i++) {
            if (dragNode[i] === dropNode) {
              return true;
            } else {
              return this.isChildNode(dropNode, dragNode[i]);
            }
          }
        } else {
          return false;
        }
      },
      handleSelect (root, node, data) {
        this.$set(data, 'selected', true);
        this.currentNode = data;
          this.$emit('on-select-change', data);
      },
      getParentNode(parentCode, data) {
        for (let i = 0; i < data.length; i++) {
          if (data[i].classCode === parentCode) {
            return data[i];
          } else if (data[i].children) {
            return this.getParentNode(parentCode, data[i].children);
          }
        }
        return false;
      }
    }
  }
</script>
<style lang="less">
  .node {
    &-selected {
      background-color: #d5e8fc;
     }
  }
</style>


 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值