2015-04-24 53 views
2

我開始更好地學習angularJS,並且我注意到AngularJS試圖強調從控制器和封裝分離視圖。其中一個例子就是人們告訴我DOM操作應該在指令中進行。我現在已經掌握了它,以及如何使用注入當前元素的鏈接函數允許出色的行爲功能,但這並不能解釋我總是遇到的問題。如何訪問2個以上DOM元素「AngularJS方式」?

例如: 我有一個側欄,我想通過單擊按鈕打開。在沒有使用硬編碼的javascript/jquery選擇器來抓取邊欄的情況下,在按鈕的指令鏈接函數中沒有辦法做到這一點,這是我在angularJS(硬編碼dom選擇器)中非常不贊同的,因爲它打破了關注點分離。我想一個解決這個問題的方法是讓每個我希望操作屬性指令的元素以及它的鏈接函數,將它的元素屬性引用到dom工廠中,以便每當指令需要訪問除本身以外的元素時,它可以調用返回元素的dom工廠,即使它不知道它來自哪裏。但是,這是「角度的方式」?

我這樣說是因爲在我當前的項目中,我使用硬編碼的選擇器,這已經是一種痛苦,因爲我經常更換我的css。必須有更好的方法來訪問多個DOM元素。有任何想法嗎?

+1

通常可以使用範圍變量(或服務)和「ng-class」或「ng-show」等來做這種事情。兩者都允許使用ng-animate。好的做法是在添加更多自己的dom操作之前考慮如何使用內置指令的數據綁定 – charlietfl

回答

1

有很多方法可以解決這個問題。

一種方法是創建一個創建sidebar指令,該指令響應「明確定義的」廣播消息來打開/關閉邊欄。

.directive("sidebar", function(){ 
    return { 
    templateUrl: "sidebar.template.html", 
    link: function(scope, element){ 
     scope.$root.$on("openSidebar", function(){ 
     // whatever you do to actually show the sidebar DOM content 
     // e.x. element.show(); 
     }); 
    } 
    } 
}); 

然後,一個按鈕可以在某些控制器調用函數打開側邊欄:

$scope.openSidebar = function(){ 
    $scope.$root.$emit("openSidebar"); 
} 

另一種方法是使用$sidebar服務 - 這有點類似於angularui-如何$modal作品bootstrap,但可以更簡化。

+0

是作用域。$ root與$ rootScope相同嗎?我怎樣才能實現你的$ scope。$ root。$在控制器中使用「controller as」語法發佈,我通過$ scope變量將屬性綁定到「this」對象? –

+0

是的,'scope。$ root'是'$ rootScope'的引用。從視圖(控制器或不),你應該能夠'ng-click =「$ root。$ emit('openSidebar')」' –

1

好吧,如果你有一個按鈕,一個指令,你需要的元素是指令外,你可以把類的元素,你需要在你的指令切換爲屬性

<button my-directive data-toggle-class="sidebar">open</button> 

然後

App.directive('myDirective', function() { 
    return { 
     restrict: 'A', 
     link: function(scope, element, attrs) { 
      angular.element('.' + attrs.toggleClass).toggleClass('active'); 
     } 
    }; 
} 

您不會總是將鏈接元素參數與您不幸需要操作的內容匹配起來。有很多「角度的方法」來解決這個問題。

你甚至可以這樣做:

<div ng-init="isOpen = false" class="sidebar" ng-class="{'active': isOpen}" ng-click="isOpen = !isOpen"> 
    ... 
</div> 
+0

Mmhh ..這是相當不錯的,我沒有想到,但不知何故我覺得添加一個屬性只會將更新重複的類/ ID選擇器從JavaScript的工作轉移到HTML。儘管如此,它仍然比硬編碼更好。如果沒有更好的答案,我會記住它並標記爲最佳答案。另外,感謝ng級的解決方案,我完全忘了這一點,而且你對它的做法很有幫助。 –

1

的指令相互通過活動交流的最佳方式。它也與問題的分離保持一致。您的按鈕可以在$rootScope$broadcast,以便所有示波器都能聽到它。你會發射和事件,如sidebar.open。然後,側邊欄指令將監聽該事件並對其執行操作。

+0

哦哇,我從來沒有這樣做過,也許是因爲我還沒有購買$廣播服務。作爲一個簡單的問題,我想一個人不應該使用$ rootScope,甚至更少的指令,糾正我,如果我錯了。 –

+0

大多數不使用$ rootScope的理性背後是不把所有的業務價值放在那裏,以避免範圍的湯。只使用現有的作用域,'$ broadcast'和'$ emit'可能不會將事件傳遞給指令,因爲兄弟指令會錯過事件。 – Enzey

+1

這是一種相同的論點,你不應該在控制器中使用'$ element'。我遵循曼陀羅的說法,您不應該在控制器中進行DOM操作,以便您可以更輕鬆地測試控制器。不過,我已經在控制器中使用'$ element'來訪問控制器定義元素的屬性,並使代碼更加健全,而不是在指令的鏈接中執行,並將新值推入控制器。 – Enzey