Web 组件中的拖放 API(Lit)

问题描述 投票:0回答:1

背景语境

我成功地使用普通元素和事件监听器学习了拖放 API 的基础知识。但我想看看是否可以使用 Web 组件重新创建相同的功能。

在“普通”Web 组件中重新创建拖放功能时遇到一些麻烦后,我决定尝试一下 Lit(因为它建立在我喜欢的现有标准之上)。

问题

使用准系统设置来学习。

就这么简单,控制台仅触发

dragstart
事件,但不触发
drag
dragend
事件。

这是课程:

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)
    }

    // fires repeatedly while dragging
    onDrag(evt) {
        evt.preventDefault()
        console.log(evt.type, `${evt.target.localName} (${evt.target.textContent})`, evt)
    }

    // always fires, even for unsuccessful drops
    onDragEnd(evt) {
        console.log(evt.type, evt.target.localName, evt)
    }

    render() {
        return html`<b>⠿</b><slot></slot>`
    }
}

customElements.define('li-dragdrop', LiDragdrop)

除了最基本的 HTML 文档之外,这是我在

body
中拥有的所有内容:

<li-dragdrop>Item 1</li-dragdrop>
<li-dragdrop>Item 2</li-dragdrop>

我拖动元素。我看到

dragstart
已记录到控制台,但没有其他内容。

我不确定这是否与 Shadow DOM 事件或 Lit 有关。

我只知道我能够使用标准 HTML 元素和一些函数来使用完整的 API。一旦我尝试使用 Web 组件,我就无法获得比

dragstart
更进一步的结果。

为什么?

javascript html events drag-and-drop web-component
1个回答
0
投票

您的 Lit 代码所做的就是为您创建 ShadowDOM。
这是下面 native Web 组件中的 1 行。

注意:自己进行拖放是一件痛苦的事情,您需要几天时间才能让它按照您想要的方式工作。一旦您完成了一个应用程序的操作,您就可以在每个应用程序中执行此操作。

最大的旅行:

  • 尝试处理太多事件,这就是为什么下面的
    dragover
    被限制为1秒。
    也许使用
    dragenter
    dragleave
  • dataTransfer
    恕我直言,这是一种痛苦。
    我通常存储有关在父节点上拖动的内容的信息..认为
    <chess-board>
  • 不要忘记事件
    touchmove
    及其所有触摸屏的表兄弟
  • shadowDOM 内的 DOM 节点过多;下面的代码有一个。

<drag-box color="red"></drag-box>
<drag-box color="yellow"></drag-box>
<drag-box color="blue"></drag-box>

<script>
  console.clear();
  customElements.define('drag-box', class extends HTMLElement {
    constructor() {
      super()
        .attachShadow({mode:'open'})
        .innerHTML = `<style>:host {
                                display: inline-block;
                                background: var(--color); width: 100px; height: 100px;
                                cursor: grab                          
                              }</style>`;
      this.updatedragover = true;
    }
    connectedCallback() {
      this.color = this.color;
      this.setAttribute("draggable", true);
      // let JS default "handleEvent" on the class handle the event
      this.addEventListener("dragstart", this);
      this.addEventListener("dragend"  , this);
      this.addEventListener("dragover" , this);
    }
    handleEvent(e) {
      if (this[e.type]) this[e.type](e); // exec method
    }
    dragover(e) {
      if (this.updatedragover) { // only once a second
        this.updatedragover = false;
        console.log('dragover', this.color);
        setTimeout(() => this.updatedragover = true, 1000);
      }
    }
    dragstart(e) {
      console.log(e.type, this.color);
      this.style.opacity = 0.3;
      // this.closestElement("chess-board").dragging = this
    }
    dragend(e) {
      console.log(e.type, this.color);
      this.style.opacity = 1;
    }
    get color()  { return this.getAttribute("color") || "grey" }
    set color(c) { this.style.setProperty("--color", c)        }
  })
</script>

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.