javascript - 在 ng-mousedown 中绑定(bind)文档 mouseup

标签 javascript jquery angularjs jquery-events mousedown

我想要一些东西以 ng-mousedown 开始并以 mouseup 结束。我还希望如果鼠标离开该元素,当鼠标按钮保持按下状态时,某些事情会继续发生。在普通 Javascript 中实现此功能的一种非常常见的方法是在元素 mousedown 事件中绑定(bind)文档 mouseup 事件,like so :

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

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

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!"'); 
      }
    });
  });

最佳答案

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

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

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

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

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

您可以查看documentation或阅读更多 here .

关于javascript - 在 ng-mousedown 中绑定(bind)文档 mouseup,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32109923/

相关文章:

javascript - 如何将附加参数传递给 ajax 回调函数?

jQuery-重新定位 div onclick 以与表格行对齐

javascript - 在我的应用程序中声明和链接 Controller 时遇到问题

javascript - 将默认语言环境设置为国际化 API?

javascript - 尽管参数可用,但模式验证失败

c# - 级联下拉列表不适用于 Jquery

javascript - jQuery .find() 在 IE 中不返回数据,但在 Firefox 和 Chrome 中返回数据

node.js - express 错误 500 错误 : Failed to lookup view "/app/views/admin/users"

css - Angular 条件模态背景

javascript - 将鼠标悬停在图像上时播放视频并显示文本