AngularJS 沒有元素選擇器算不算一個缺點?
同事問我了一個問題:
AngularJS 做麵包屑導航條,想獲取當前導航(原話是 class 是 active 的 a 標籤的 id)。AngularJS 沒有內置的元素選擇器(angular.element 得和 jQuery 共存時才能起到元素選擇器的作用,否則只是一個 jqLite 的 wrapper)。我覺得 AngularJS 可能是故意不給元素選擇器功能的,所以我想出的辦法是:把圖中代碼 [item.name == path] 改為 [compare(item, path)],並且定義:然而這樣的缺點是,AngularJS 每次內部輪詢都要調用我寫的 compare 方法,若是其中有性能瓶頸,就會很卡。另一種有同樣缺陷的辦法是:
$scope.compare= function(item, path){
if (item.name === path){
$scope.itemId = item.id;
return true;
}
return false;
}
個人覺得雖然 AngularJS 給出了和 jQuery 完全不同的思路,但還是偶爾會想要一個元素選擇器。綜上所述,大家覺得 AngularJS 到底應該有元素選擇器嗎?為什麼?-----補充-----有些回答說 querySelectors 和 getElementByTagName 什麼的,這些是個前端就會用行么,還可以把 zepto 的 qsa 方法copy 一份過來用。但這都不對題,因為我想知道我們到底需要不需要一個元素選擇器,求一個看起來很有道理的答案,謝謝。
$scope.watch(path, function(){
//輪詢所有的 item
//或者高級一點,用一個 hash 直接指向對應的 item
});
-
先回答一個問題:思維方式不一樣。
拿到這個ID幹嘛用?
你朋友的思路還是以DOM為中心的, 先有DOM, 再找數據。
而不是以DATA為中心, 先有數據,再渲染為DOM。按angular的思維, 應該是你在$scope里有一個breadcrumbList, 用來標識麵包屑的追蹤。
然後這個breadcrumbList才去渲染出你要的麵包屑引導。而不是反過來, 先渲染再去找ID。如下源碼, 要不就是breadcrumbList的最後一個item表示當前, 要不item就有一個active屬性。
&
參考下這個源碼吧: ncuillery/angular-breadcrumb · GitHub
補充一下:
angular並不是不需要控制DOM, 而是絕大部分情況下, 你不需要操作。在Directive裡面,本身就可以用原生的選擇器了, 或者你加一個zepto就ok了。在非Directive裡面, 就絕對不應該操作DOM。如果你發現有這種情況, 歡迎補充到: 在你日常使用AngularJS中,有哪些情況是覺得需要操作DOM的? 我們來分析分析。
-1. 由於不兼顧低端瀏覽器,所以,在Angular支持的瀏覽器中,基本的現代選擇器都是直接可用的,無需封裝
2. 寫Angular程序,首要考慮的是分層,尤其是UI層的隔離,正常情況下,不應在directive之外的所有代碼中出現對DOM的操作,如果有的話,我打一個比方給你:控制器是你男朋友,DOM是家裡的小金庫,他可以努力掙錢,但錢是怎麼到你小金庫的,他不需要管。你最需要注意的就是不讓他碰錢,然後你在這裡扮演directive的角色,如果他想碰,必須通過你,否則很可能出現一個後果,他動了錢,你不知道,然後帳不平了……
哎我舉例太沒節操了,教壞小朋友,總之是這個意思,代碼就看天豬的
贊同天豬(劉勇) ,angular是面向你的數據編程,不是面向DOM編程。
我個人對angular的理解是,90%的case只需要關心數據,剩下10%,有5%的情況,應該用directive來解決,還剩下5%,用directive不如自己跟DOM搏鬥來得爽快。
===============說起來有點可惜,07年的時候在項目中其實寫過一個mini的類似angular的框架,但項目代碼的版權是客戶的,沒法開源出來,後來工作一忙,說自己另外寫一個來開源吧也不了了之了,然後angular出來之後,想想,洗洗睡吧。。。這說明你沒看這個經典的帖子,目前已經6225贊了
javascript - "Thinking in AngularJS" if I have a jQuery background?話說,究竟是控制界面(Dom)還是界面就是我程序的一部分絕逼是兩種思維啊Angular的思維模式與其餘框架都不一樣,它所有的數據都不是從頁面取的,反過來說,頁面所有的數據都是從scope中讀出來的,每次scope做出改變,頁面會跟著變,所以active這個dom也只是表象,你應該從scope中找到引起active改變的那個data,然後獲取它。不是很喜歡Angular,很多在以前的case中只需要讀一個dom取數據來獲取當前狀態的需求,在angular中都需要一個變數來存儲它,並且還要在html裡面寫js,寫判斷語句,寫調用方法,非常丑。
不在Controller裡面使用選擇器的原因,我想是為了方便測試。
一個Controller就是一個pure js class。試想一個Controller裡面要用到DOM,測試這個Controller就不能單獨進行了。栗子:function PageController() {
var vm = this;
vm._state = {
page: 1
};
vm.gotoPage = gotoPage;
vm.goForward = goForward;
vm.goBack = goBack;
vm.getCurrentPage = getCurrentPage;
function gotoPage(page) {
vm._state.page = page;
}
function goForward() {
var page = vm._state.page + 1;
gotoPage(page);
}
function goBack() {
var page = vm._state.page - 1;
gotoPage(page);
}
function getCurrentPage() {
return vm._state.page;
}
}
Test case:
describe("PageController test", function() {
var pageCtrl = new PageController(),
page = 3;
beforeEach(function() {
pageCtrl.gotoPage(page);
});
it("should go to custom page", function () {
pageCtrl.gotoPage(5);
expect(pageCtrl.getCurrentPage()).toBe(5);
});
it("should go forward", function(){
pageCtrl.goForward();
expect(pageCtrl.getCurrentPage()).toBe(page + 1);
});
it("should go back", function(){
pageCtrl.goBack();
expect(pageCtrl.getCurrentPage()).toBe(page - 1);
});
it("should return current page", function(){
expect(pageCtrl.getCurrentPage()).toBe(page);
});
});
推薦閱讀:
※Backbone.js 的最佳應用場景有哪些?
※關於mvc的理解?
※前端 MVC 和伺服器端有哪些差別?
TAG:前端開發 | JavaScript | MVC | MVVM | AngularJS |