したがって、100 個の li を持つ ul がある場合、各 li に ng-clicks が必要ですか、またはイベントを ul にバインドし、それを li の種類の jquery に委任する方法はありますか? これは良くなりますか、それとも悪くなりますか? 100 のイベントがありますか、それとも最終的に 1 つのイベントだけですか?
4 に答える
アンギュラーはリピーターでイベント委任を行わないようです。誰かがそれについて github で問題を開きました。議論は、それが実際にパフォーマンスの向上につながるかどうかです。
回避策があるかもしれませんが、jQuery が必要です。親要素で使用する特別なディレクティブを作成し、その dom ノードにリスナーを登録します。
次に示すのは、子ノードがクリックされたときに呼び出される関数名が渡される例です。また、リッスンする子ノードを識別するのに役立つセレクターも渡されます。angular の jquery 実装はメソッドのみを提供するため (実際の要素へのイベント リスナーの登録に限定されます)、またはメソッドbind
にアクセスするには jQuery をロードする必要があります。on
delegate
HTML
<ul click-children='fun' selector='li'>
<li ng-repeat="s in ss" data-index="{{$index}}">{{s}}</li>
</ul>
定義された関数はコントローラーで定義されており、インデックスが渡されることを期待しています
$scope.fun = function(index){
console.log('hi from controller', index, $scope.ss[index]);
};
ディレクティブは$parse
、イベント リスナーから呼び出される関数に式を変換するために使用します。
app.directive('clickChildren', function($parse){
return {
restrict: 'A',
link: function(scope, element, attrs){
var selector = attrs.selector;
var fun = $parse(attrs.clickChildren);
element.on('click', selector, function(e){
// no need to create a jQuery object to get the attribute
var idx = e.target.getAttribute('data-index');
fun(scope)(idx);
});
}
};
});
プランカー: http://plnkr.co/edit/yWCLvRSLCeshuw4j58JV?p=preview
注: 関数は、isolate scopes を使用してディレクティブに委任できます{fun: '&'}
。これは一見の価値がありますが、これにより複雑さが増します。
ここにある jm- の例に基づいて、このディレクティブのより簡潔で柔軟なバージョンを作成しました。共有したいと思いました。クレジットはjm-に行きます;)
私のバージョンでは、関数名を $scope[ fn ]( e, data ) として呼び出そうとしましたが、正常に失敗しました。
クリックされた要素からオプションの json オブジェクトを渡します。これにより、Angular 式を使用して、呼び出されるメソッドに多数のプロパティを渡すことができます。
HTML
<ul delegate-clicks="handleMenu" delegate-selector="a">
<li ng-repeat="link in links">
<a href="#" data-ng-json='{ "linkId": {{link.id}} }'>{{link.title}}</a>
</li>
</ul>
Javascript
コントローラーの方法
$scope.handleMenu = function($event, data) {
$event.preventDefault();
$scope.activeLinkId = data.linkId;
console.log('handleMenu', data, $scope);
}
ディレクティブ コンストラクター
// The delegateClicks directive delegates click events to the selector provided in the delegate-selector attribute.
// It will try to call the function provided in the delegate-clicks attribute.
// Optionally, the target element can assign a data-ng-json attribute which represents a json object to pass into the function being called.
// Example json attribute: <li data-ng-json='{"key":"{{scopeValue}}" }'></li>
// Use case: Delegate click events within ng-repeater directives.
app.directive('delegateClicks', function(){
return function($scope, element, attrs) {
var fn = attrs.delegateClicks;
element.on('click', attrs.delegateSelector, function(e){
var data = angular.fromJson( angular.element( e.target ).data('ngJson') || undefined );
if( typeof $scope[ fn ] == "function" ) $scope[ fn ]( e, data );
});
};
});
誰かが貢献したい場合は、フィードバックをお待ちしております。
より複雑なアプリケーションからこれを抽出したため、handleMenu メソッドはテストしませんでした。
上記の BradGreens の delegateClicks から始めて、georg のコードをいくつか適応させて、handleMenu 関数を $scope のより深い位置に配置できるようにしました (例: $scope.tomato.handleMenu)。
app.directive('delegateClicks', function () {
return function ($scope, element, attrs) {
var fn = attrs.delegateClicks.split('.').reduce(function ($scope, p) { return $scope[p] }, $scope);
element.on('click', attrs.delegateSelector, function (e) {
var data = angular.fromJson(angular.element(e.target).data('ngJson') || undefined);
if (typeof fn == "function") fn(e, data);
});
};
});