在 ng-mousedown 中绑定文档 mouseup
Bind document mouseup in ng-mousedown
我想在 ng-mousedown
开始并在 mouseup
结束。如果鼠标离开元素,我还希望在鼠标按钮保持按下状态时继续发生某些事情。在 vanilla Javascript 中实现这一点的一种非常常见的方法是在元素 mousedown
事件中绑定文档 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
, and 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-mouseup
和 ng-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 之外执行的。为了使您的数据绑定工作,您应该像这样用 $scope.$apply
包装它:
$scope.$apply(function () {
$scope.value = 'done!';
});
请注意 ng-mouseup
工作正常,您可以在按钮上方触发 mouseup 时看到它。但是如果你把鼠标移到按钮外面$(document).one('mouseup'..)
事件就会发生。
请记住,您必须使用 $scope.$apply
包装所有外部回调(JQuery HTTP 回调,DOM 未绑定 ng-* 指令的事件,setTimeout
,等)如果你需要它与 AngularJS 绑定或观察者一起工作。但是请三思 - 在另一个 $scope.$apply
中调用 $scope.$apply
会导致错误。
你可以翻阅documentation or read more here.
我想在 ng-mousedown
开始并在 mouseup
结束。如果鼠标离开元素,我还希望在鼠标按钮保持按下状态时继续发生某些事情。在 vanilla Javascript 中实现这一点的一种非常常见的方法是在元素 mousedown
事件中绑定文档 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
, and 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-mouseup
和 ng-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 之外执行的。为了使您的数据绑定工作,您应该像这样用 $scope.$apply
包装它:
$scope.$apply(function () {
$scope.value = 'done!';
});
请注意 ng-mouseup
工作正常,您可以在按钮上方触发 mouseup 时看到它。但是如果你把鼠标移到按钮外面$(document).one('mouseup'..)
事件就会发生。
请记住,您必须使用 $scope.$apply
包装所有外部回调(JQuery HTTP 回调,DOM 未绑定 ng-* 指令的事件,setTimeout
,等)如果你需要它与 AngularJS 绑定或观察者一起工作。但是请三思 - 在另一个 $scope.$apply
中调用 $scope.$apply
会导致错误。
你可以翻阅documentation or read more here.