【问题标题】:Drag'n'drop dataTransfer.getData empty拖放 dataTransfer.getData 为空
【发布时间】:2015-04-13 18:31:43
【问题描述】:

我试图让拖放工作,但我似乎完全错过了 getData/setData 的工作原理。

我正在使用此代码 (http://jsfiddle.net/ASKte/218/)

var el = angular.element(document.getElementById('drag'));
el.attr("draggable", "true");
el.bind("dragstart", function(e) {
    e.dataTransfer.setData('text', 'Where have you gone?!?!')         
});

var target = angular.element(document.getElementById('drop'));
target.bind("dragover", function(e) {
    if (e.preventDefault) {
        e.preventDefault(); // Necessary. Allows us to drop.
    }
    return false;
});

target.bind("dragenter", function(e) {
    console.debug(e.dataTransfer.types);
    console.debug(e.dataTransfer.getData('text'));
});

我在这里使用 AngularJS,因为这是一段大得多的代码的 sn-p。

由于某种原因,在底部正方形上拖动顶部正方形时,getData('text') 的值始终为空,但我不知道为什么...

有什么想法吗?

提前致谢。

【问题讨论】:

    标签: javascript angularjs drag-and-drop


    【解决方案1】:

    数据仅在拖放时可用,这是一项安全功能,因为当您碰巧在网页上拖动某些内容时,网站可能会抓取数据。

    var el = angular.element(document.getElementById('drag'));
    el.attr("draggable", "true");
    el.bind("dragstart", function(e) {
        e.dataTransfer.setData('text', 'Where have you gone?!?!')         
    });
    
    var target = angular.element(document.getElementById('drop'));
    target.bind("dragover", function(e) {
        if (e.preventDefault) {
            e.preventDefault(); // Necessary. Allows us to drop.
        }
        return false;
    });
    
    target.bind("drop", function(e) {
        console.debug(e.dataTransfer.types);
        console.debug(e.dataTransfer.getData('text'));
    });  
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div id="drag" style="width: 100px; height: 100px; background-color: blue;"></div>
    
    <div id="drop" style="width: 100px; height: 100px; background-color: green;"></div>

    【讨论】:

    • 啊,我明白了,那太糟糕了。我想根据拖动的内容进行一些动态样式更改。我想我必须想出其他解决方案。
    • @Robba 你找到解决方案了吗?
    • @Z.Khullah 您可以在拖动期间检查 dataTransfer.types,这将是您作为第一个参数传递给 setData 的字符串数组。因此,您可以例如调用 setData('text', 'my drop data') 和 setData('dropzone1', 'dummy'),然后在 dragover 上检查类型数组以查看它是否包含 dropzone1 或 dropzone2,然后您将知道要设置哪个 dropEffect。
    • @BrianS 的建议是正确的答案,超级容易实现!请注意 .types 会自动小写,请注意将类型与您的小写 id 进行比较(或确保您的 id 为小写)
    • 这是一个令人讨厌的限制。我了解安全风险,但这应该是可选的附加安全措施,例如限制谁可以看到正在拖动的内容(例如,只有启动拖动的相同 URL/视口)。用例:我需要知道正在拖动哪个特定项目(不仅仅是什么类型的项目),以决定是否可以将其拖放到另一个项目上,以便在用户悬停时提供反馈。
    【解决方案2】:

    如果您真的需要访问其他放置事件中的数据,请使用dataTransfer.types。使用JSON.parseJSON.stringify 和编码/解码大写字符来绕过dataTransfer.types 变成小写。

    设置数据:

    event.dataTransfer.setData(encodeUpperCase(JSON.stringify(value)), '');
    

    获取数据:

    const data = JSON.parse(decodeUpperCase(event.dataTransfer.types[0]))
    

    编码/解码是这样的:

      const UPPERCASE_PREFIX = '^{';
      const UPPERCASE_SUFFIX = '}^';
    
      function encodeUpperCase(str: string): string {
        return str.replace(/([A-Z]+)/g, `${UPPERCASE_PREFIX}$1${UPPERCASE_SUFFIX}`);
      }
    
      function decodeUpperCase(str: string): string {
        const escapeRegExp = (escape: string) => ['', ...escape.split('')].join('\\');
    
        return str.replace(
          new RegExp(`${escapeRegExp(UPPERCASE_PREFIX)}(.*?)${escapeRegExp(UPPERCASE_SUFFIX)}`, 'g'),
          (_, p1: string) => p1.toUpperCase()
        );
      }
    

    它有效,但你可能会在此过程中召唤克苏鲁。

    【讨论】:

      猜你喜欢
      • 2022-09-29
      • 2016-08-06
      • 2020-08-30
      • 1970-01-01
      • 1970-01-01
      • 2016-12-06
      • 1970-01-01
      • 2016-09-25
      • 1970-01-01
      相关资源
      最近更新 更多