在AngularJS中访问被点击的元素
在AngularJS中访问被点击的元素
我对AngularJS还比较陌生,怀疑自己没有掌握某个概念。我还在使用Twitter Bootstrap,并且已经加载了jQuery。
工作流程:用户从列表中点击一个链接,"master"部分更新,被点击的链接获得active类。
基本的HTML标记:
- Clients
- Employees
- jQuery(".list-holder").on('click', 'a', function(event){
event.preventDefault();
jQuery(".list-holder li").removeClass('active');
jQuery(this).parent('li').addClass('active');
});
但是我无法弄清楚如何将Angular和jQuery集成起来完成这个任务,因为我正在使用Angular从服务器获取主列表(以JSON形式)并更新页面上的列表。
如何进行集成?一旦我在Angular控制器函数内部,似乎无法找到我点击的元素。
控制器:
function adminController($scope) { $scope.setMaster = function(obj) { // 如何获取点击元素的父li? console.log(obj); } }
在AngularJS中,我们可以使用以下语法来获取点击事件(以及其中的目标元素)(注意$event
参数传递给setMaster
函数):
function AdminController($scope) { $scope.setMaster = function(obj, $event){ console.log($event.target); } }
然而,这种解决方法并不是非常符合AngularJS的方式。AngularJS的重点在于模型操作。我们可以改变模型,然后让AngularJS来处理渲染。
在AngularJS中解决这个问题的方式(不使用jQuery和不需要传递$event
参数)是:
<div ng-controller="AdminController">
<ul class="list-holder">
<li ng-repeat="section in sections" ng-class="{active : isSelected(section)}">
<a ng-click="setMaster(section)">{{section.name}}</a>
</li>
</ul>
<hr>
{{selected | json}}
</div>
控制器中的方法如下:
$scope.setMaster = function(section) { $scope.selected = section; } $scope.isSelected = function(section) { return $scope.selected === section; }
完整的jsFiddle示例在这里:http://jsfiddle.net/pkozlowski_opensource/WXJ3p/15/
需要注意的是,$event
只有在标记中传递时才起作用:ng-click="setMaster(section, $event)"
。
是否有关于这个问题的任何AngularJS文档的链接?
没有,它必须传递给函数。不过,实际上,在控制器中引用DOM特定的内容可能不是一个好主意。通常情况下,当使用$event时,它是用于停止传播或类似的上下文中:<a ng-click="doSomething(); $event.stopPropagation()">Click Just Me</a>
我在使用$event.target时遇到了问题,因为我的按钮内有一个图标。所以,有时候目标结果是按钮,有时候是图标(取决于我点击的位置)。我使用$event.currentTarget代替target,它完美地工作。
请注意,只有在需要进行低级DOM操作时才需要传递$event
参数。如果按照AngularJS的方式解决问题,绝对不需要这个参数。
你可以在不从视图中传递$event的情况下访问函数中的DOM元素,查看下面的解决方案。
需要注意的是,访问$event.target的另一个用例是用于操作可访问性的焦点。不幸的是,当涉及到可访问性时,并没有"Angular方式",因为作者在这方面基本上没有关注。
谢谢!我之前不知道ng-directive函数可以获取参数$event。
虽然像这样使用$event.target
可能不是"Angular方式",但我觉得在一个有很多项需要监听器来评估更改的大型ng-repeat
列表中,并不高效。点击一个元素意味着整个列表中的每个项都必须重新评估,对吗?为什么不只是用$event.target
来针对那个特定的项进行操作,例如切换CSS类。你觉得呢?我正在开发一个Phonegap应用,需要尽可能提高性能。
我还想推荐使用$event.currentTarget
而不是$event.target
。如果带有ng-click的元素有子元素,如果点击子元素,$event.target
就会变成子元素。而$event.currentTarget
将始终指向具有指定ng-click的元素。
是正确的。我不会否认$event.target
不是Angular方式,但是这里展示的Angular方式非常低效。isSelected会在每个ng-repeat迭代的每个元素上被多次调用。在应用程序初始化之后,它是3*n,对于每次点击,它是2*n。所以在上面的示例中,只有3个元素,当它加载并且您点击一次时,isSelected总共被调用了18次。现在将其扩展到带有真实列表的真实生产应用程序。有时候Angular方式并不总是最好的方式。