无论出于什么原因,onPaste事件似乎都不会在可拖动元素上触发.(已在Firefox和Chrome上选中)

有没有某种方法(黑客或不黑客)使它工作?

我一直在try :

  • 添加contenteditable="true",但这 destruct 了用户体验,因为我不希望用户真正编辑内容
  • 添加透明/不可见的输入或contentitable元素,但这要么会 destruct paste事件,要么会拖动
  • onMouseDown上设置可拖动的仅为true,在onMouseUp上设置为false,但粘贴事件仍然失败
  • 用paste将可拖动的元素包装成一个元素,用paste将元素包装成可拖动的元素,仍然失败.

下面是一个最小的例子来重现这个问题:playground.

Vue.createApp({
  setup() {
    const pasteEvents = Vue.ref([]);

    async function onPaste(event) {
      console.log(event);
      pasteEvents.value.push("Paste from Element " + event.target.dataset["element"])
    }

    return {
      pasteEvents,
      onPaste
    }
  }
}).mount("#app");
.wrapper {
  display: flex;
  flex-direction: column;
  gap: 16px;
  .paste-area {
    padding: 16px;
    background: #00000011;
    &:focus {
      border: 2px dashed red;
    }
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.8/vue.global.min.js"></script>

<div id="app">
  <div class="wrapper">
    Click on an element and press Ctrl+V
    <div :draggable="true">
      <div class="paste-area" data-element="A" tabindex="0" @paste="onPaste">
        Element A (draggable)
      </div>
    </div>
    <div class="paste-area" tabindex="0" data-element="B" @paste="onPaste">
      Element B (no draggable)
    </div>
    {{ pasteEvents }}
  </div>
</div>

(这是一个vueplayground ,但它不会改变任何东西)

操场上有趣的部分:

<div
    draggable="true"
    tabindex="0"
    @paste="onPaste"
>
    Element A (draggable, does not work)
</div>
<div
    tabindex="0"
    @paste="onPaste"
>
    Element B (no draggable, works)
</div>

(对于不熟悉Vue的人来说,@paste基本上就是addEventListener("paste", () => ...))

在第一个元素上按Ctrl+V不会触发paste功能,但在第二个元素上工作正常.

编辑:似乎对每个剪贴板事件都是一样的(复制/剪切/粘贴)

推荐答案

我找不到任何原因的规格说明为什么这不会在这种情况下触发,焦点元素设置得很好,键盘事件在他们应该触发的地方触发,但话又说回来,我发现W3C的MIDI规格是松散的,就像他们的许多UI规格一样.

One workaround is to actually set the contenteditable, and then prevent any edits from the user by listening to the beforeinput event.
If you want to get rid of the caret, while you can't, you can at least "hide" it by setting the caret-color to transparent.

// Sorry I don't know Vue enough to make it there
document.addEventListener("beforeinput", (evt) => {
  // You may need to adjust the selector
  if (evt.target.closest("[draggable='true'] [contenteditable]")) {
    evt.preventDefault();
  }
});

Vue.createApp({
  setup() {
    const pasteEvents = Vue.ref([]);

    async function onPaste(event) {
      console.log(event);
      pasteEvents.value.push("Paste from Element " + event.target.dataset["element"])
    }

    return {
      pasteEvents,
      onPaste
    }
  }
}).mount("#app");
.wrapper {
  display: flex;
  flex-direction: column;
  gap: 16px;
  .paste-area {
    padding: 16px;
    background: #00000011;
    /* added a few more specific selectors to handle focus in contenteditable */
    &:focus,&:focus-visible,&:focus-within {
      border: 2px dashed red;
      outline: 0;
    }
  }
}
/* You may need to adjust the selector */
[draggable="true"] [contenteditable] {
  caret-color: transparent;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.8/vue.global.min.js"></script>

<div id="app">
  <div class="wrapper">
    Click on an element and press Ctrl+V
    <div :draggable="true">
      <div :contenteditable class="paste-area" data-element="A" tabindex="0" @paste="onPaste">
        Element A (draggable)
      </div>
    </div>
    <div class="paste-area" tabindex="0" data-element="B" @paste="onPaste">
      Element B (no draggable)
    </div>
    {{ pasteEvents }}
  </div>
</div>

现在唯一的区别是光标实际上仍然在这里,因此如果你做了Shift Arrow,文本将从光标的位置被选中.如果这真的是一个问题,你可能可以通过听selectionchange事件来解决这个问题.

Javascript相关问答推荐

如何编辑代码FlipDown.js倒计时?

仅圆角的甜甜圈图表

Phaser框架-将子对象附加到Actor

Redux工具包查询(RTKQ)端点无效并重新验证多次触发

基于变量切换隐藏文本

如何在Javascript中的控制台上以一行形式打印循环的结果

在nextjs服务器端api调用中传递认证凭证

提交链接到AJAX数据结果的表单

IF语句的计算结果与实际情况相反

DOM不自动更新,尽管运行倒计时TS,JS

元素字符串长度html

使用Document.Evaluate() Select 一个包含撇号的HTML元素

如何更改Html元素S的 colored颜色 ,然后将其褪色为原始 colored颜色

如何在AG-Grid文本字段中创建占位符

为什么我的Navbar.css没有显示在本地主机页面上?

JQuery使用选项填充HTMLSELECT并设置默认结果,默认结果显示为空

我如何才能让p5.js在不使用实例模式的情况下工作?

JavaScript -如何跳过某个字符(S)来打乱字符串中的字符

如何缩小函数中联合返回类型的范围

错误400:当我试图在React中使用put方法时,该字段是必需的