html5 原生拖放踩坑笔记

890 阅读2分钟

html5 原生拖放踩坑笔记

1. 原生拖拽时元素被拖拽移动的样式无法自定义

解决方案: 不使用原生拖拽,用鼠标 mousedown mousemove mouseup 等事件模拟拖拽,克隆拖拽节点

2. dragstart 事件必须设置节点 draggable 才能起作用

3. 节点必须指定 dragover 事件才能拖入响应 drop 事件

4. IE 下 event.dataTransfer 只支持 'text' 类型

5. 某些双核浏览器兼容模式 event.dataTransfer.getData 无法获取数据

解决方案: 通过外部变量来存储数据

// 拖拽数据
// 用以解决双核浏览器兼容模式下无法通过 dataTransfer.getData 获取数据
let dragData = null

// 拖拽开始
function onDragStart(event) {
  event.dataTransfer.dropEffect = 'move'
  dragData = 'my transfer data'
  event.dataTransfer.setData('text', dragData)
}

// 拖拽结束,清理拖拽数据
function onDragEnd() {
  dragData = null
}

// 释放
function onDrop(event) {
  const data = event.dataTransfer.getData('text') || dragData 
}

6. 火狐浏览器 drop 时会打开新页签

解决方案: drop 事件加入 event.preventDefault()event.stopPropagation() 阻止该行为

// 释放
function onDrop(event) {
  // 阻止火狐将数据新页签打开
  event.preventDefault()
  event.stopPropagation()
}

7. 浏览器如果安装了采集插件,并且拖拽节点包含图片元素或图片背景,可能会被拦截拖拽。

解决方案: 拖拽节点包裹图片节点,不要放同一个节点上。

<div class="drag-item" draggable ondragstart="ondragstart">
  <div class="drag-bg" style="background-image: url('img.png');"></div>
</div>

8. Chrome 浏览器下拖拽节点移动时会包含外层节点内容

解决方案: 暂无

9. 拖拽区域内的输入框文本无法选中,IE下甚至无法聚焦

解决方案: 监听拖拽区域鼠标点击的元素,如果是输入框则禁止拖拽

<div class="drag-area" :draggable="draggable" @dragstart="onDragstart">
  <input type="text" />
</div>
{
  data() {
    return {
      inputLock : false // 输入中禁用拖拽
    }
  },

  computed: {
    // 是否允许拖拽
    draggable() {
      return !this.inputLock
    }
  },
  
  mounted() {
    this.$el.addEventListener('mousedown', this.checkMousedown)
  },

  destroyed() {
    this.$el.removeEventListener('mousedown', this.checkMousedown)
  },

  methods: {
    // 鼠标点击检测
    // 解决:拖拽区域内的输入框文本无法选中,IE下甚至无法聚焦
    checkMousedown(e) {
      if (['input', 'textarea'].includes(e.target.tagName.toLowerCase())) {
        clearTimeout(this.inputLockTimer)
        this.inputLock = true
        this.inputLockTimer = setTimeout(() => (this.inputLock = false), 1000)
      }
    }
  }
}

10. 通过指定的拖拽句柄来拖动父元素

解决方案: 同方案 9 中类似,监听 mousedown 元素,如果不是句柄元素则禁止拖拽