![](/img/trans.png)
[英]AngularJS : What is the best way to bind to a global event in a directive
[英]AngularJs : what is the best way to changing DOM elements when there are “global”?
我來自 JQuery,我使用 AngularJs 的第一步讓我有點困惑......
我的情況 :
我有一個面板(#floatingpanel),它用 css(頂部:-50px)隱藏在視口之外。
我在我的應用程序的最深處有一個鏈接 (a.trigger),當您單擊該鏈接時,面板的“頂部”屬性會從“-50px”變為“0px”以使其可見(您單擊切換可見性)。 面板就在我頁面主容器的這一端,但它的鏈接在數百個其他div
。
讓我們來看看 DOM 結構:
<body>
<div class="main-wrapper" ng-app="myapp">
<div class="app">
<div class="many-things">
[...]
<a href="#" class="trigger" ng-click="toggleMyPanelVisibility()">
Click here to see the panel
</a>
[...]
</div>
</div><!-- .app -->
<div id="floatingpanel">
Hey ! I was hidden !
</div>
</div> <!-- #mainwrapper -->
</body>
在 jQuery 中,它將是:
$('a.trigger').click( function(e) {
e.preventDefault();
var el = $('#floatingpanel');
var top = el.css('top');
if (top<0) el.css('top', 0);
else el.css('top', -50);
});
我怎樣才能用 AngularJs 做到這一點?
我會這樣做:
var app = angular.module('myapp');
app.run(["$rootScope", function($rootScope) {
// Toggle du myaccountpanel
$rootScope.floatingpanelVisibility = false;
$rootScope.toggleMyPanelVisibility = function() {
$rootScope.floatingpanelVisibility = !$rootScope.floatingpanelVisibility;
var panel = angular.element( $('#floatingpanel') );
var top = -50;
if ($rootScope.floatingpanelVisibility)
top = 0;
panel.css({'top': top });
}
});
好的,它有效,但是...我想如果我繼續這種方式,我的app.run
很快就會超載,不是嗎? 我也可以用我的“主包裝器”上的控制器來做到這一點,但這很愚蠢,它已經是我的應用程序范圍了!
我怎樣才能用指令做到這一點?
解決這個爛攤子的“最佳方法”是什么?
我在 Angular 中看到的兩種最常見的方法是通過 rootscope 消息傳遞或通過服務。 該服務是兩者中更清潔/更好的。
接受的答案假設一切都在同一個控制器下,這顯然不是構建 OP 所描述內容的方式。
想象一個頁面由一堆小部件組成——無論是子視圖還是指令,都由它們自己的獨立控制器處理。 這是處理 OP 在 Angular 中描述為“所有這些東西”的正確方法。
現在,您需要一種在一個事件中觸發事件的方法,該事件可由任何其他事件響應。 如果您定義了一個服務,比如“pageEventService”,它公開一個函數來啟動/觸發事件“togglePanel”,以及一個保存狀態的屬性 - “panelIsVisible”,您可以在需要觸發的任何地方引用該服務事件,並在面板中引用它以響應該值。
.controller('SomeControllerThatCanTriggerEvent', function(pageEventService) {
var model = this;
model.togglePanel = pageEventService.togglePanel;
});
在此控制器控制的標記中的某處...
<a ng-click="model.togglePanel()">Toggle the Panel</a>
在面板控制器中...
.controller('PanelController', function(pageEventService) {
var model = this;
model.panelIsVisible = pageEventService.panelIsVisible;
});
並在面板標記中...
<div id="TheAlmightyPanel" ng-show="model.panelIsVisible">... cool stuff here ...</div>
這比 rootscope 消息傳遞更清晰,因為您可以明確說明 pageEventService 可以做什么以及誰引用它。 你可以在視圖、子視圖和指令中使用它 - 無論你需要它。
你正在做的事情可以在不接觸 DOM 的情況下完成,使用內置的 angular 指令本身,這里我只是使用ng-show
指令,如果你想把特定的類放到它然后只使用ng-class
,以及任何動畫可以僅作為 css 動畫提供,並且通過包含ngAnimate
模塊它變得更好,您可以使用添加的類名來提供 動畫行為。
例子:-
<div class="main-wrapper" ng-app="myapp">
<div ng-controller="panelController as panel">
<a href="#" class="trigger" ng-click="panel.toggle($event)">Click here to see the panel</a>
<div ng-show="panel.show" class='panel'>
<!-- <div ng-class="{'show':panel.show}"> and define css rules for panel.show-->
Hey ! I was hidden !
</div>
</div>
</div>
在控制器panelController
控制器中
angular.module('app').controller('panelController', function($scope){
var vm = this;
vm.show = false;
this.toggle = function($event){
$event.preventDefault();
vm.show = !vm.show;
}
});
我在這里只是使用控制器作為語法,如果您願意,您也可以使用 $scope ,您甚至可以將其轉換為指令。
根據您的問題更新進行編輯:
創建控制器並在需要時使用內置的 angular 指令沒有什么不好,而不是在您確實不需要時使用 jquery/手動 dom 操作。
<body>
<div class="main-wrapper" ng-app="myapp" ng-controller="mainController as main">
<div class="app">
<div class="many-things">
[...]
<a href="#" class="trigger" ng-click="main.togglePanel($event)">Click here to see the panel</a>
[...]
</div>
</div><!-- .app -->
<div id="floatingpanel" ng-show="panel.show">
Hey ! I was hidden !
</div>
</div> <!-- #mainwrapper -->
</body>
這可能是您遇到的錯誤答案,因為您似乎不打算創建控制器或重新設計視圖。
.directive('togglePanel', function(jQuery){
return {
restrict: 'A',
link:function(scope, elm, attr){
elm.on('click', handleToggle);
scope.$on('$destroy', function(){
elm.off('click', handleToggle);
});
function handleToggle(e){
var $target = jQuery(attr.togglePanel);//Get the target
//Do what you want to do with the target
}
}
}
}).constant('jQuery', window.jQuery);
並將其用作:
<a href="#" class="trigger" toggle-panel="#floatingPanel">Click here to see the panel</a>
好的 ! 感謝@PSL,我明白如果我在我的 ng-app 元素上設置一個控制器,這不是問題。
<div class="main-wrapper" ng-app="myapp" ng-controller="mainController as main">
我認為這是一個不好的做法......
有了這個“mainController”,我可以輕松地與我的 2 個元素進行交互:通過ng-click
與鏈接進行交互,通過ng-class
(或ng-show
等)與面板進行交互。我看不到更好的方法。 如果我避免使用這個“mainController”,我可以制定一個指令,但要觸摸我的面板,它會迫使我訪問范圍之外的 DOM...
我絕對必須將我的想法從 jquery 方式轉變為 angular 方式( 此鏈接可以提供幫助)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.