我意识到当我安装ng-mouseover
和ng-mouseout
事件回调时,我的整个AngularJS变得非常慢。
很快,我意识到2个回调,只需移动鼠标就会导致其他AngularJS函数一次又一次地重新评估。
<html ng-app="phonecatApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
<script src="controllers.js"></script>
</head>
<body ng-controller="PhoneListCtrl"
ng-mouseover="onScreen($event)"
ng-mouseout="offScreen($event)">
<div id="dummy"
ng-show="isLoggedIn()">
<ul>
<li ng-repeat="phone in phones">
<span>{{phone.name}}</span>
<p>{{phone.snippet}}</p>
</li>
</ul>
</div>
</body>
</html>
var phonecatApp = angular.module('phonecatApp', []);
phonecatApp.controller('PhoneListCtrl', function ($scope) {
$scope.phones = [
{'name': 'Nexus S',
'snippet': 'Fast just got faster with Nexus S.'},
{'name': 'Motorola XOOM™ with Wi-Fi',
'snippet': 'The Next, Next Generation tablet.'},
{'name': 'MOTOROLA XOOM™',
'snippet': 'The Next, Next Generation tablet.'}
];
$scope.onScreen = function (e) {
};
$scope.offScreen = function (e) {
};
$scope.isLoggedIn = function() {
console.log("isLoggedIn : " + new Date().getTime());
return true;
};
});
在上面的示例中,ng-mouseover
和ng-mouseout
只是简单地调用空函数。但是,如果我尝试将鼠标移到浏览器上,我会发现isLoggedIn
被多次触发。
我可以知道为什么AngularJS有这样的行为吗?我怎么能避免这样的?
答案 0 :(得分:6)
这是非常期待的行为:
mouseover / mouseout事件冒出来(请参阅event bubbling)DOM树。这意味着即使您将鼠标悬停在页面内的任何内容上(在课程的正文标记内),它也会冒泡并运行在正文上注册的mouseover / mouseout事件处理程序。
Angular运行所有观察者(digest cycle),以便更新视图上的任何DOM绑定,以反映作为events gets triggered {{3}}通过scope.$apply()
的范围属性的任何更改。
上一步导致isLoggedIn()
表达式@ ng-show="isLoggedIn()"
再次被评估,因为ng-show指令也会创建一个观察者。
相反,如果适用,请使用mouseenter/mouseleave
,因为这些事件不会冒泡,只会在您关注页面时运行。
<body ng-controller="PhoneListCtrl"
ng-mouseenter="onScreen($event)"
ng-mouseleave="offScreen($event)">
另一件事是尽量避免在角度绑定中绑定函数表达式,尝试绑定到属性。
示例:您应该在适用的地方设置$scope.status.isLoggedIn
,并在ng-show
@ ng-show="status.isLoggedIn"
中使用该标记。当然,如果您确实需要阻止任何摘要发生,请创建自定义指令而不是ng-mouseenter/leave
并在那里执行滑动菜单显示。那就是你必须手动完成,而不是通过DOM范围绑定为你做角度。