【问题标题】:Bind document mouseup in ng-mousedown在 ng-mousedown 中绑定文档 mouseup
【发布时间】:2015-08-20 05:05:24
【问题描述】:

我想在ng-mousedown 开始并在mouseup 结束。如果鼠标离开元素,我还希望在鼠标按钮保持按下状态时继续发生某些事情。在 vanilla Javascript 中实现这一点的一种非常常见的方法是在元素 mousedown 事件 like so 中绑定一个文档 mouseup 事件:

HTML:

<button onMouseDown='onMouseDown()'>Click Me</button>
<div id="val"></div>

JS:

function onMouseDown() {
  var el = document.querySelector('#val'),
      changeValue = function() {
        el.innerHTML = 'done!';
        document.removeEventListener('mouseup', changeValue);
      };
  
  el.innerHTML = 'waiting for mouseup...';

  document.addEventListener('mouseup', changeValue);
}

我在使用 jQuery's one()angular.element.oneaddEventListener / removeEventListener 的 Angular 中实现此行为时遇到问题:

HTML:

<div ng-app="MyApp" ng-controller="AppCtrl">
  <div>Note that 'done!' is not rendered, despite 'mouseup' being logged to the console</div>
  <button ng-mousedown='changeValue()'>Click Me</button>
  <div>{{value}}</div>   
</div>

JS(jQuery 的one()):

angular
  .module('MyApp', [])
  .controller('AppCtrl', function($scope) {
    $scope.changeValue = function() {
      console.log('mousedown');
      $scope.value = 'waiting for mouseup...';  
      
      $(document).one('mouseup', function() {
        console.log('mouseup');
        $scope.value = 'done!';
      });
    }
  });

JS (angular.element.one):

angular
  .module('MyApp', [])
  .controller('AppCtrl', function($scope) {
    $scope.changeValue = function() {
      console.log('mousedown');
      $scope.value = 'waiting for mouseup...';  
      
      angular.element(document).one('mouseup', function() {
        console.log('mouseup');
        $scope.value = 'done!';
      });
    }
  });

JS (addEventListener/removeEventListener):

angular
  .module('MyApp', [])
  .controller('AppCtrl', function($scope) {
    $scope.changeValue = function() {
      var changeValue = function() {
        console.log('mouseup');
        $scope.value = 'done!';
        document.removeEventListener('mouseup', changeValue);
      };
      
      console.log('mousedown');
      $scope.value = 'waiting for mouseup...';  
      
      document.addEventListener('mouseup', changeValue);
    }
  });

我还尝试利用 ng-mouseupng-mouseleave like this

HTML:

<div ng-app="MyApp" ng-controller="AppCtrl">
  <div>While clicking the button, move the mouse off of the button and release the mouse button. Note that 'done!' is not rendered, despite 'mouseup' being logged to the console</div>
  <button ng-mousedown='mouseDown()' ng-mouseup="mouseUp()" ng-mouseleave="mouseLeave()">Click Me</button>
  <div>{{value}}</div>  
</div>

JS:

angular
  .module('MyApp', [])
  .controller('AppCtrl', function($scope) {
    $scope.mouseDown = function() {
      console.log('mousedown');
      $scope.value = 'waiting for mouseup...';  
    }
    $scope.mouseUp = function() {
      console.log('mouseup');
      $scope.value = 'done!';
    }
    $scope.mouseLeave = function() {
      if ($scope.value && $scope.value.indexOf('waiting') > -1) {
        console.log('mouseleave, binding mouseup'); 
        $(document).one('mouseup', function() {
           $scope.mouseUp();
        });
      }
    }
  });

结果是一样的。 $scope.mouseUp 被执行,但 'done!' 永远不会被渲染。 This creates additional problems with $scope.$watch:

HTML:

<div ng-app="MyApp" ng-controller="AppCtrl">
  <div>value never === 'done!' in $scope.$watch</div>
  <button ng-mousedown='changeValue()'>Click Me</button>
  <div>{{value}}</div>   
</div>

JS:

angular
  .module('MyApp', [])
  .controller('AppCtrl', function($scope) {
    $scope.changeValue = function() {
      console.log('mousedown');
      $scope.value = 'waiting for mouseup...';  
      
      $(document).one('mouseup', function() {
        console.log('mouseup');
        $scope.value = 'done!';
      });
    }
    $scope.$watch('value', function(value) {
      if (value === 'done!') {
        console.log('value set to "done!"'); 
      }
    });
  });

【问题讨论】:

    标签: javascript jquery angularjs jquery-events mousedown


    【解决方案1】:

    不知道为什么这个问题已经一个多月没有答案了。

    这里的主要问题很简单——更新$scope.value 的代码是在AngularJS 之外执行的。为了使您的数据绑定正常工作,您应该使用$scope.$apply 将其包装起来,如下所示:

    $scope.$apply(function () {
      $scope.value = 'done!';                
    });
    

    请注意ng-mouseup 可以正常工作,当在按钮上方触发 mouseup 时您可以看到它。但是如果你把鼠标移到按钮之外$(document).one('mouseup'..)事件就会发生。

    请记住,如果您需要使用 AngularJS 绑定,则必须使用 $scope.$apply 包装所有外部回调(JQuery HTTP 回调、未使用 ng-* 指令绑定的 DOM 事件、setTimeout 等)或观察者。但请三思 - 在另一个 $scope.$apply 中调用 $scope.$apply 会导致错误。

    您可以浏览documentation 或阅读更多here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-17
      • 2014-02-05
      • 1970-01-01
      • 1970-01-01
      • 2012-11-13
      • 1970-01-01
      • 2014-07-24
      • 1970-01-01
      相关资源
      最近更新 更多