VUE+H5跨组件元素拖拽并传递数据;拖拽结束自动计算布局;以及如何配合element的可拖拽tree使用

VUE+H5跨组件元素拖拽并传递数据;拖拽结束自动计算布局;以及如何配合element的可拖拽tree使用

1.vue+H5实现跨组件拖拽与数据传递思路:

(1)可拖拽组件元素的dragstart事件中,将相关数据暂存在vuex;
(2)可放置组件元素的drop事件中,接收vuex中暂存的数据;
(3)清空vuex的暂存数据;

2.vue+H5实现跨组件拖拽与数据传递实现;

(1)可拖拽组件:

<template>
  <div @dragstart="drag">
  </div>
</template>
<script>
import { mapGetters, mapMutations} from 'vuex'
export default {
  props: {
  },
  computed: {
    ...mapGetters(['curDragCell'])
  },
  methods: {
    /**
     * 开始拖动
     */
    drag() {
      this.setCurDrag(this.item)
    },
    ...mapMutations(["setCurDrag"])
  },
};
</script>

(2)vuex设计

	state: {
        curDragCell: null,
    },
    mutations: {
        setCurDrag(state, v = {}) {
            state.curDragCell = JSON.parse(JSON.stringify(v));
        },
    },
    actions: {
    },
    getters: {
        curDragCell: state => state.curDragCell,
    },

(3)可放置拖拽组件

<template>
  <div @drop="drop">
  </div>
</template>
<script>
import { mapGetters, mapMutations } from "vuex";
export default {
...
computed: {
    ...mapGetters(["curDragCell"]),
  },
methods:{
...mapMutations(["setCurDrag"]),
	drop(e) {
	//在这里通过this.curDragCell获取当前被拖拽的组件相关数据并处理
	...
	//处理结束后清空vuex中的暂存数据
	this.setCurDrag(null);
	}
}
}
</script>

3.拖拽结束自动计算布局

如果希望被拖拽过来的元素自动实现从左到右的自动布局,或者拖拽到其他元素中间实现插入布局,则需要一些坐标上的计算;

计算思路:
(1)在可放置拖拽组件的drop事件中,遍历所有参与布局的元素,获取其相对与画布元素的x,y坐标,以及其自身宽高,以计算出其中心坐标;
(2)获取拖拽结束事件的鼠标坐标,与上一步的所有参与布局的元素的中心坐标进行x、y坐标上的比较,根据需求算出权重值;(需要注意的是,从左到右从上到下排列时,计算权重是y轴坐标的权重需要比x轴坐标权重高出一个或几个数量级,具体数值由画布元素宽度决定,不知道计算原理的话越大越好。)
(3)权重最大(或最小)的元素位置便是需要处理的位置,根据鼠标坐标x坐标轴和该元素坐标x坐标轴比较,算出插入位置是左还是右,并实现插入。

代码实现:

/**
     * 拖拽结算
     */
    drop(e) {
      e.preventDefault();
      //通过x,y坐标判断插入位置
      if (!this.curDragCell) return;
      if (this.rules.length === 0) {
        this.rules.push(this.curDragCell);
      } else {
        let drawing = this.$refs.rulesInput;
        let pos = drawing.getBoundingClientRect();
        let curX = e.x - pos.x;
        let curY = e.y - pos.y;
        let cells = (this.$refs.rulesInputCell.map((item) => item.$el)).filter(item=> this.curDragDom?!item.className.includes('cur'):true)
        let minimum = null;
        for (let i = 0; i < cells.length; i++) {
          let item = cells[i];
          let position =
            curX - (item.offsetLeft + item.offsetWidth / 2) >= 0 ? 1 : 0; //1:右侧,0:左侧
          let distanceItem = {
            weight:
              (position
                ? Math.abs(curX - item.offsetLeft - item.offsetWidth)
                : Math.abs(curX - item.offsetLeft)) +
              Math.abs(curY - item.offsetTop - item.offsetHeight / 2) * 10000, //加重y轴距离权重
            position: position,
            index: i,
          };
          if (!minimum || distanceItem.weight <= minimum.weight) {
            minimum = distanceItem;
          }
        }
        if (minimum.index === 0 && minimum.position === 0) {
          this.rules.unshift(this.curDragCell);
        } else if (
          minimum.index === this.rules.length - 1 &&
          minimum.position === 1
        ) {
          this.rules.push(this.curDragCell);
        } else {
          this.rules.splice(
            minimum.index + minimum.position,
            0,
            this.curDragCell
          );
        }
        this.setCurDrag(null);
      }
    },

4.如何配合element的可拖拽tree使用

如果想要从element的tree组件中直接拖拽元素出来使用,其实有非常简便的方法;

思路:因为el-tree自带可拖拽的功能,且本身实现原理也是H5的拖拽,所以的拖拽相关事件都可以复用,只要在el-tree组件做一些配置即可

	<el-tree
      ref="tree"
      :data="data"
      @node-drag-start="handleDragStart"
      draggable
      :allow-drop="allowDrop"
      :allow-drag="allowDrag"
    ></el-tree>
    <script>
    	export default {
    		/**
     * 拖动开始
     */
    handleDragStart(node) {
      node.data.name = node.data.elePathNameCh;
      this.setCurDrag(node.data);
    },
    /**
     * 不允许在此区域结束拖动
     */
    allowDrop() {
      return false;
    },
     /**
     * 判断是否允许拖动
     */
    allowDrag(node) {
      if(this.onlyAcLeaf){
         return this.isAllowDrag&&node.isLeaf;
      }else{
        return this.isAllowDrag
      }
    },
    	}
    </script>
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值