vue 无需任何插件 使用draggable实现 拖拽移动dom 拖拽排序等

需求描述:

        最近在一个需求中遇到一个需要实现一个拖拽某行数据到一个列表中,从而在对应的列表中展示该被拖拽行的数据!

实现:

        实现过程全程没有使用什么插件,但是有很多插件可以使用。作者实现的过程是使用html5的新特性---draggable!而且可以看到此特性兼容性较好。

于是乎,我写了个大概的demo如下:

这里面其实还用了 事件代理,将@dragstart事件放在父盒子中,防止生成的的li标签过多,注册的事件监听过多。

 <section class="drag-demo">
    <div class="can-drag-list">
      <ul
        @dragstart="onDragStart"
        @dragend="onDragEnd"
        @dragenter="onDragEnter"
      >
        <li
          v-for="drag in dragList"
          :key="drag.id"
          :data-id="drag.id"
          draggable
        >
          {{ drag.name }}
        </li>
      </ul>
    </div>
    <div 
      class="drag-into-box"
      ref="dropTo"
      @drop="onDrop"
      @dragover="onDragOver" 
    />
  </section>

写了很多盒子层级,说明这个是可以在多级中嵌套使用,不会影响。js代码如下

export default {
  name: 'Drag',
  data() {
    return {
      storageLi: {
        storageText: '',
        storageId: null,
        dropDownId: null
      },
      dragList: [{
        id: 1,
        name: '名称1'
      }, {
        id: 2,
        name: '名称2'
      }, {
        id: 3,
        name: '世界大会就'
      }, {
        id: 4,
        name: '四大'
      }, {
        id: 5,
        name: '反对法'
      }]
    };
  },
  created() {},
  methods: {
    // 开始拖动的事件
    onDragStart (event) {
      if(event.target.nodeName !== 'LI') return
      console.log("开始传递", event.target.innerText)
      this.storageLi.storageText =  event.target.innerText
      this.storageLi.storageId =  event.target.getAttribute('data-id');
    },
    // 阻止默认行为
    onDragOver (event) {
      event.preventDefault()
    },
    // 拖拽进去对应dom放下的事件
    onDrop (event) {
      let newElement = document.createElement('div')
      newElement.innerText = this.storageLi.storageText;
      const dropToDom = this.$refs.dropTo
      dropToDom.appendChild(newElement)
    },
  }
}

在这里面需要注意的是:拖拽放下的事件需要使用@dragover触发的事件中阻止默认行为,否则并不会触发@drop事件。我们可以看到拖拽放下的事件中用到了生成dom并插入的方法,但是我们用了vue开发其实可以不用这样,可以定义一个展示数组,通过操作这个数组的行为来在模板中动态展示列表。

列表拖拽排序:

        当然,这个可以实现操作的并不完全仅限于拖到另一个dom,在开发中,我们也会有需求可以实现拖拽排序之类的功能。代码如下

    // 自己列表内拖拽结束事件触发
    onDragEnd (event) {
      if(event.target.nodeName !== 'LI') return
      // 处理数组位置对调
      let dragList = this.dragList
      const sourceId = this.storageLi.storageId
      const targetId = this.storageLi.dropDownId
      // 查找源元素和目标元素的索引位置
      const sourceIndex = dragList.findIndex(item => item.id == sourceId);
      const targetIndex = dragList.findIndex(item => item.id == targetId);
      // 如果找到了源元素和目标元素的索引位置
      if (sourceIndex !== -1 && targetIndex !== -1) {
        // 如果源元素在目标元素之前,将源元素插入目标元素之后的位置
        if (sourceIndex < targetIndex) {
          dragList.splice(targetIndex + 1, 0, dragList[sourceIndex]);
          dragList.splice(sourceIndex, 1);
        }
        // 如果源元素在目标元素之后,将源元素插入目标元素之后的位置,再删除原来的源元素位置
        else if (sourceIndex > targetIndex) {
          dragList.splice(targetIndex, 0, dragList[sourceIndex]);
          dragList.splice(sourceIndex + 1, 1);
        }
      }
      console.log(dragList, 'dragList')
      this.$set(this, 'dragList', dragList)
    },
    // 拖拽进入的事件
    onDragEnter (event) {
      const target = event.target;
      if(target.nodeName !== 'LI') return
      // 通过 target.getAttribute 获取元素上的自定义属性值
      const dropDownId = target.getAttribute('data-id');
      this.storageLi.dropDownId = dropDownId
    }

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值