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 元素,如果不是句柄元素则禁止拖拽