Lit Web Components中Drag-and-Drop API仅触发dragstart事件问题
问题原因与解决方案
问题核心出在dragstart事件处理函数中的evt.preventDefault()调用——拖拽API规定,dragstart事件不能被阻止默认行为,一旦执行这个方法,浏览器会直接取消整个拖拽操作的初始化流程,后续的drag(拖拽过程中持续触发)和dragend(拖拽结束时触发)事件自然不会被触发。
你之前用普通元素能正常工作,大概率是当时的代码没有在dragstart中调用preventDefault(),这个问题和Web Components/Lit的Shadow DOM无关,纯粹是拖拽API的使用错误。
修改后的代码
只需移除onDragStart里的evt.preventDefault()即可:
class LiDragdrop extends LitElement { static styles = css` :host { display: block } :host b { display: inline-block } ` constructor() { super() } connectedCallback() { super.connectedCallback() this.setAttribute('draggable', 'true') this.addEventListener('dragstart', this.onDragStart, {passive: false}) this.addEventListener('drag', this.onDrag) this.addEventListener('dragend', this.onDragEnd) } onDragStart(evt) { // 移除这行错误的阻止默认行为代码 // evt.preventDefault() evt.dataTransfer.effectAllowed = 'move' evt.dataTransfer.setData('text/html', this.outerHTML) console.log(evt.type, `${evt.target.localName} (${evt.target.textContent})`, evt) } onDrag(evt) { console.log(evt.type, `${evt.target.localName} (${evt.target.textContent})`, evt) // drag事件无需阻止默认行为,不影响核心拖拽流程 } onDragEnd(evt) { console.log(evt.type, evt.target.localName, evt) } render() { return html`<b>⠿</b><slot></slot>` } } customElements.define('li-dragdrop', LiDragdrop)
补充说明
- 拖拽API中,仅在
dragover、drop这类事件里阻止默认行为才有实际意义(比如允许元素被放置,需要阻止dragover的默认行为)。 dragstart的默认行为就是启动拖拽操作,阻止它等于直接取消整个拖拽动作,事件链会直接中断。
内容的提问来源于stack exchange,提问作者Zearin
相关产品推荐
相关产品推荐

