HTML5本地的DragEnter/DragLeave事件不断交替触发

4

我在我的angular应用程序中使用本地HTML拖放功能,发现了这个事件闪烁问题。

这个答案没有解决我的问题,因为他们手动移动元素。我仍然使用本地实现。

我的简化代码:

var app = angular.module('app', []);
app.directive('amDnd', function() {
  return {
    scope: true,
    link: function($scope, $element, $attr) {
      var el = $element[0];
      el.draggable = true;

      el.addEventListener('dragenter', function dragEnter(e) {
        console.log($scope.$id, 'dragEnter');
      }, false);
      el.addEventListener('dragleave', function dragEnter(e) {
        console.log($scope.$id, 'dragleave');
      }, false);

    }
  };
});
div[am-dnd] {
  border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <div am-dnd>
    <p>DRAG ME</p>
  </div>
  <div am-dnd>
    <h3>DRAG OVER THIS AREA</h3>
    <p>See the console, drag enter and leave are fired again and again while draging over
    </p>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi quisquam, eaque, iure mollitia similique magnam voluptatem blanditiis distinctio nemo! Laboriosam porro iste maiores sequi magnam similique ad, in at. Omnis.</p>
  </div>

</div>

2个回答

5
我有一种感觉,即“闪烁”问题的根源在于第二个am-dnd指令的每个子元素都会触发dragenter/dragleave事件。这里有一个Stack Overflow问题讨论了解决方法,可以查看这里
你可以声明一个类似这样的CSS规则:
.child-elements {
   pointer-events: none;
}

...并在事件触发期间使用jqLite将此类应用于 am-dnd 指令的所有子元素:

element.children().addClass("child-elements");

我制作了一个 JSFiddle,在第一个指令被拖到第二个指令时,"闪烁"事件被最小化,但第二个指令拖过第一个指令仍存在一些问题。不过,我希望这能指引你朝着正确的方向前进。

var app = angular.module('app', []);
app.directive('amDnd', function () {
    return {
        scope: true,
        link: function (scope, element, attrs) {
            element.attr('draggable', 'true');

            element.on('dragenter', function () {
                element.children().addClass("child-elements");
                console.log('dragEnter');
            });
            element.on('dragleave', function () {
                element.children().removeClass("child-elements");
                console.log('dragleave');
            });
        }
    };
});

谢谢你的回答,它指引我找到了问题并解决了它。你的解决方案是可行和正确的,但在我的项目中,我使用了嵌套指令,因此我想出了一个更适合我的需求的不同解决方案。再次感谢你,祝你有愉快的一天 ;) - Luckylooke
@Luckylooke 太棒了 - 很高兴能对你有所帮助。 - alex

1
最适合我的需求的解决方案:

var app = angular.module('app', []);
app.directive('amDnd', function() {
  return {
    scope: true,
    link: function($scope, $element, $attr) {
      var el = $element[0],
        counter = 0;
      el.draggable = true;

      el.addEventListener('dragenter', function dragEnter(e) {
        if (e.target === el && !counter) {
          console.log($scope.$id, 'dragEnter');
        }
        counter++;
      }, false);
      el.addEventListener('dragleave', function dragLeave(e) {
        counter--;
        if (e.target === el && !counter) {
          console.log($scope.$id, 'dragleave');
        }
      }, false);

    }
  };
});
div[am-dnd] {
  border: 2px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <div am-dnd id='id1'>
    <p>DRAG ME</p>
  </div>
  <div am-dnd id='id2'>
    <h3>DRAG OVER THIS AREA</h3>
    <p>See the console, drag enter and leave are fired again and again while draging over
    </p>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi quisquam, eaque, iure mollitia similique magnam voluptatem blanditiis distinctio nemo! Laboriosam porro iste maiores sequi magnam similique ad, in at. Omnis.</p>
  </div>

</div>


我不得不编辑我的答案,因为复制粘贴错误(缺少counter--;)。现在应该没问题了。 - Luckylooke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接