javascript - isarray - jquery find attribute




如果我有jQuery背景,“在AngularJS中思考”? (10)

假設我熟悉在jQuery開發客戶端應用程序,但現在我想開始使用AngularJS 。 你能描述一下必要的範式轉變嗎? 以下是一些可能有助於您確定答案的問題:

  • 如何以不同方式構建和設計客戶端Web應用程序? 最大的區別是什麼?
  • 我應該停止做什麼/使用什麼; 我應該開始做什麼/使用什麼呢?
  • 有任何服務器端考慮因素/限制嗎?

我不是在尋找jQueryAngularJS之間的詳細比較。


你能描述一下必要的範式轉變嗎?

勢在必行與陳述

使用jQuery,您可以一步一步地告訴DOM需要發生什麼。使用AngularJS您可以描述您想要的結果,但不能描述如何執行此操作。更多關於here。另外,請查看Mark Rajcok的答案。

如何以不同方式構建和設計客戶端Web應用程序?

AngularJS是一個使用MVC模式的完整客戶端框架(查看其圖形表示)。它非常注重關注點的分離。

最大的區別是什麼? 我應該停止做什麼/使用什麼; 我應該開始做什麼/使用呢?

jQuery是一個庫

AngularJS是一個漂亮的客戶端框架,高度可測試,它結合了許多很酷的東西,如MVC,依賴注入,數據綁定等等。

它側重於關注點和測試(單元測試和端到端測試)的分離,這有助於測試驅動的開發。

最好的方法是通過他們的精彩教程。你可以在幾個小時內完成這些步驟; 但是,如果你想掌握幕後的概念,它們包含了無數的參考資料以供進一步閱讀。

有任何服務器端考慮因素/限制嗎?

您可以在已經使用純jQuery的現有應用程序上使用它。但是,如果您想充分利用AngularJS功能,可以考慮使用RESTful方法對服務器端進行編碼。

這樣做將允許您利用他們的資源工廠,它創建服務器端RESTful API的抽象,並使服務器端調用(獲取,保存,刪除等)非常容易。


1.不要設計頁面,然後使用DOM操作進行更改

在jQuery中,您設計了一個頁面,然後將其設置為動態。 這是因為jQuery是為增強而設計的,並且從這個簡單的前提中獲得了令人難以置信的增長。

但是在AngularJS中,您必須從頭開始考慮您的架構。 而不是首先考慮“我有這塊DOM,我想讓它做X”,你必須從你想要完成的事情開始,然後去設計你的應用程序,然後最後去設計你的視圖。

2.不要使用AngularJS擴充jQuery

同樣,不要從jQuery做X,Y和Z的想法開始,所以我只是在模型和控制器的基礎上添加AngularJS。 當你剛剛開始時,這真的很誘人,這就是為什麼我總是建議新的AngularJS開發人員根本不使用jQuery,至少在他們習慣於“Angular Way”做事之前。

我在這里和郵件列表上看到很多開發人員使用150或200行代碼的jQuery插件創建這些精心設計的解決方案,然後他們將這些代碼粘合到AngularJS中,其中包含一系列令人困惑和錯綜複雜的回調和$apply ; 但他們最終讓它發揮作用! 問題在於,在大多數情況下,jQuery插件可以在AngularJS中以一小部分代碼重寫,突然間一切都變得易於理解和直接。

最重要的是:在解決問題時,首先要“在AngularJS中思考”; 如果你想不出解決方案,請問社區; 如果完全沒有簡單的解決方案, 那麼隨時可以找到jQuery。 但是不要讓jQuery成為拐杖或者你永遠不會掌握AngularJS。

3.始終從架構的角度思考

首先要知道單頁應用程序應用程序 。 他們不是網頁。 因此,我們需要像服務器端開發人員一樣思考,而不是像客戶端開發人員那樣思考。 我們必須考慮如何將我們的應用程序劃分為單獨的,可擴展的,可測試的組件。

那你怎麼做的呢? 你如何“在AngularJS中思考”? 以下是一些與jQuery形成對比的一般原則。

該觀點是“官方記錄”

在jQuery中,我們以編程方式更改視圖。 我們可以將下拉菜單定義為ul如下所示:

<ul class="main-menu">
    <li class="active">
        <a href="#/home">Home</a>
    </li>
    <li>
        <a href="#/menu1">Menu 1</a>
        <ul>
            <li><a href="#/sm1">Submenu 1</a></li>
            <li><a href="#/sm2">Submenu 2</a></li>
            <li><a href="#/sm3">Submenu 3</a></li>
        </ul>
    </li>
    <li>
        <a href="#/home">Menu 2</a>
    </li>
</ul>

在jQuery中,在我們的應用程序邏輯中,我們將使用以下內容激活它:

$('.main-menu').dropdownMenu();

當我們只看這個視圖時,並不是很明顯這裡有任何功能。 對於小型應用,這很好。 但對於非平凡的應用程序,事情很快就會變得混亂和難以維護。

但是,在AngularJS中,視圖是基於視圖的功能的官方記錄。 我們的ul聲明將是這樣的:

<ul class="main-menu" dropdown-menu>
    ...
</ul>

這兩個做同樣的事情,但在AngularJS版本中,任何看模板的人都知道應該發生什麼。 每當開發團隊的新成員加入時,她都可以查看這個,然後知道有一個名為dropdownMenu的指令在其上運行; 她不需要直截了當地回答正確的答案或篩選任何代碼。 該觀點告訴我們應該發生什麼。 更清潔。

AngularJS的新手開發人員經常會問一個問題:如何查找特定類型的所有鏈接並在其上添加指令。 當我們回复時,開發人員總是大吃一驚:你沒有。 但你不這樣做的原因是這就像是半jQuery,半AngularJS,並沒有好處。 這裡的問題是開發人員試圖在AngularJS的上下文中“執行jQuery”。 那永遠不會好起來的。 該觀點官方記錄。 在指令之外(以下更多內容),您永遠不會永遠不會更改DOM。 並且指令在視圖中應用,因此意圖很明確。

記住:不要設計,然後標記。 你必須設計,然後設計。

數據綁定

這是迄今為止AngularJS最強大的功能之一,並且我在上一節中提到了很多需要進行各種DOM操作。 AngularJS會自動更新您的視圖,所以您不必! 在jQuery中,我們響應事件然後更新內容。 就像是:

$.ajax({
  url: '/myEndpoint.json',
  success: function ( data, status ) {
    $('ul#log').append('<li>Data Received!</li>');
  }
});

對於看起來像這樣的視圖:

<ul class="messages" id="log">
</ul>

除了混合問題,我們也有同樣的問題,表明我之前提到的意圖。 但更重要的是,我們必須手動引用和更新DOM節點。 如果我們想要刪除日誌條目,我們也必須針對DOM進行編碼。 我們如何測試除DOM之外的邏輯? 如果我們想改變演示文稿怎麼辦?

這有點凌亂,有點脆弱。 但是在AngularJS中,我們可以這樣做:

$http( '/myEndpoint.json' ).then( function ( response ) {
    $scope.log.push( { msg: 'Data Received!' } );
});

我們的觀點可能如下所示:

<ul class="messages">
    <li ng-repeat="entry in log">{{ entry.msg }}</li>
</ul>

但就此而言,我們的觀點可能如下所示:

<div class="messages">
    <div class="alert" ng-repeat="entry in log">
        {{ entry.msg }}
    </div>
</div>

而現在我們使用的是Bootstrap警報框,而不是使用無序列表。 我們永遠不必更改控制器代碼! 但更重要的是,無論日誌在何處如何更新,視圖也會發生變化。 自動。 整齊!

雖然我沒有在這裡顯示,但數據綁定是雙向的。 因此,只需執行以下操作,即可在視圖中編輯這些日誌消息: <input ng-model="entry.msg" /> 。 有很多的欣喜。

不同的模型層

在jQuery中,DOM有點像模型。 但是在AngularJS中,我們有一個單獨的模型層,我們可以以任何方式管理,完全獨立於視圖。 這有助於上述數據綁定,保持關注點的分離 ,並引入更大的可測試性。 其他答案提到了這一點,所以我就把它留在那裡。

關注點分離

以上所有內容都與這個主題相關:將您的擔憂分開。 你的觀點作為應該發生的事情的官方記錄(大部分); 你的模型代表你的數據; 你有一個服務層來執行可重用的任務; 你做DOM操作並用指令擴充你的視圖; 然後將它們與控制器粘合在一起。 在其他答案中也提到了這一點,我將添加的唯一內容涉及可測試性,我將在下面的另一部分中討論。

依賴注入

為了幫助我們分離關注點, 依賴注入 (DI)。 如果你來自服務器端語言(從JavaPHP ),你可能已經熟悉了這個概念,但如果你是一個來自jQuery的客戶端人,那麼這個概念可能看起來從愚蠢到多餘到時髦。 但事實並非如此。 :-)

從廣義的角度來看,DI意味著您可以非常自由地聲明組件,然後從任何其他組件聲明組件,只需要詢問它的實例,它就會被授予。 您無需了解加載順序,文件位置或類似內容。 電源可能不會立即可見,但我只提供一個(常見)示例:測試。

讓我們說在我們的應用程序中,我們需要一個通過REST API實現服務器端存儲的服務,並且根據應用程序狀態,還需要本地存儲。 在我們的控制器上運行測試時,我們不希望與服務器通信 - 畢竟我們正在測試控制器 。 我們可以添加一個與原始組件同名的模擬服務,注入器將確保我們的控制器自動獲取假的 - 我們的控制器不會,也不需要知道差異。

說到測試......

4.測試驅動的開發 - 永遠

這實際上是關於體系結構的第3部分的一部分,但它非常重要,我將它作為自己的頂級部分。

在您看過,使用過或編寫的所有jQuery插件中,有多少有一個附帶的測試套件? 不是很多,因為jQuery不太適合。 但AngularJS是。

在jQuery中,唯一的測試方法通常是使用示例/演示頁面獨立創建組件,我們的測試可以對其執行DOM操作。 那麼我們必須單獨開發一個組件, 然後將其集成到我們的應用程序中。 多麼不方便! 很多時候,在使用jQuery開發時,我們選擇迭代而不是測試驅動開發。 誰可以怪我們?

但是因為我們有關注點分離,我們可以在AngularJS中迭代地進行測試驅動開發! 例如,假設我們想要一個超級簡單的指令在我們的菜單中指出我們當前的路線是什麼。 我們可以在應用程序視圖中聲明我們想要的內容:

<a href="/hello" when-active>Hello</a>

好的,現在我們可以為不存在的when-active指令編寫一個測試:

it( 'should add "active" when the route changes', inject(function() {
    var elm = $compile( '<a href="/hello" when-active>Hello</a>' )( $scope );

    $location.path('/not-matching');
    expect( elm.hasClass('active') ).toBeFalsey();

    $location.path( '/hello' );
    expect( elm.hasClass('active') ).toBeTruthy();
}));

當我們運行測試時,我們可以確認它失敗了。 只有現在我們才能創建我們的指令:

.directive( 'whenActive', function ( $location ) {
    return {
        scope: true,
        link: function ( scope, element, attrs ) {
            scope.$on( '$routeChangeSuccess', function () {
                if ( $location.path() == element.attr( 'href' ) ) {
                    element.addClass( 'active' );
                }
                else {
                    element.removeClass( 'active' );
                }
            });
        }
    };
});

我們的測試現在通過我們的菜單按要求執行。 我們的開發既是迭代的, 也是測試驅動的。 妖獸爽。

從概念上講,指令不是打包的jQuery

您經常會聽到“只在指令中執行DOM操作”。 這是必要的。 善意對待它!

但是讓我們深入一點......

一些指令只是裝飾視圖中的內容(想想ngClass ),因此有時會直接進行DOM操作,然後基本完成。 但是如果指令就像一個“小部件”並且有一個模板,那麼它應該尊重關注點的分離。 也就是說,模板應該在很大程度上獨立於鏈接和控制器功能中的實現。

AngularJS附帶了一整套工具,可以輕鬆實現這一目標。 使用ngClass我們可以動態更新類; ngModel允許雙向數據綁定; ngShowngHide編程方式顯示或隱藏元素; 還有更多 - 包括我們自己寫的那些。 換句話說,我們可以在沒有 DOM操作的情況下做各種各樣的超棒。 DOM操作越少,測試指令就越容易,它們的樣式就越容易,將來它們就越容易改變,它們的可重用性和可分發性就越高。

我看到許多開發人員對AngularJS很新,使用指令作為拋出一堆jQuery的地方。 換句話說,他們認為“因為我不能在控制器中進行DOM操作,所以我會把代碼放在指令中”。 雖然這當然要好得多,但它通常仍然是錯誤的

想想我們在第3節中編寫的記錄器。即使我們把它放在一個指令中,我們仍然希望用“Angular Way”來做。 它仍然不需要任何DOM操作! 很多時候DOM操作是必要的,但它比你想像的少得多! 在應用程序中的任何位置進行DOM操作之前,請先問問自己是否真的需要。 可能有更好的方法。

這是一個快速示例,顯示了我最常見的模式。 我們想要一個可切換的按鈕。 (注意:這個例子有點人為,並且表示更複雜的情況,以完全相同的方式解決。)

.directive( 'myDirective', function () {
    return {
        template: '<a class="btn">Toggle me!</a>',
        link: function ( scope, element, attrs ) {
            var on = false;

            $(element).click( function () {
                on = !on;
                $(element).toggleClass('active', on);
            });
        }
    };
});

這有一些問題:

  1. 首先,jQuery從來都不是必需的。 我們在這裡做的一切都不需要jQuery!
  2. 其次,即使我們的頁面上已經有jQuery,也沒有理由在這裡使用它; 我們可以簡單地使用angular.element ,當我們放入沒有jQuery的項目時,我們的組件仍然可以工作。
  3. 第三,即使假設此指令需要jQuery才能工作,jqLit​​e( angular.element )將始終使用jQuery(如果已加載)! 所以我們不需要使用$ - 我們可以使用angular.element
  4. 第四,與第三個密切相關的是,jqLit​​e元素不需要包裝在$ - 傳遞給link函數的元素已經是 jQuery元素!
  5. 第五,我們在前面的章節中提到過,為什麼我們將模板內容混合到邏輯中?

這個指令可以重寫(即使對於非常複雜的情況!)更簡單如下:

.directive( 'myDirective', function () {
    return {
        scope: true,
        template: '<a class="btn" ng-class="{active: on}" ng-click="toggle()">Toggle me!</a>',
        link: function ( scope, element, attrs ) {
            scope.on = false;

            scope.toggle = function () {
                scope.on = !scope.on;
            };
        }
    };
});

同樣,模板內容在模板中,因此您(或您的用戶)可以輕鬆地將其交換為滿足任何必要樣式的模板,並且不必觸及邏輯 。 可重用性 - 熱潮!

還有所有其他好處,比如測試 - 這很容易! 無論模板中有什麼內容,指令的內部API都不會被觸及,因此重構很容易。 您可以根據需要更改模板,而無需觸及指令。 無論你改變什麼,你的測試仍然通過。

w00t!

因此,如果指令不僅僅是類jQuery函數的集合,它們是什麼? 指令實際上是HTML的擴展 。 如果HTML不需要它做某事,你可以編寫一個指令來為你做,然後就像使用它一樣使用它。

換句話說,如果AngularJS沒有開箱即用,請考慮團隊如何完成它以適應ngClickngClass等。

摘要

甚至不使用jQuery。 甚至不包括它。 它會阻止你。 當你遇到一個問題,你認為你已經知道如何在jQuery中解決,在你達到$ ,試著考慮如何在AngularJS的範圍內做到這一點。 如果你不知道,請問! 20次中有19次,最好的方法是不需要jQuery並嘗試使用jQuery解決它,為您提供更多的工作。


jQuery的

jQuery製作了一些可笑的長命令,比如getElementByHerpDerp簡短和跨瀏覽器。

AngularJS

AngularJS允許您創建自己的HTML標記/屬性,這些標記/屬性可以很好地處理動態Web應用程序(因為HTML是為靜態頁面設計的)。

編輯:

說“我有一個jQuery背景我如何在AngularJS中思考?” 就像說“我有一個HTML背景我如何在JavaScript中思考?” 您提出問題的事實表明您很可能不理解這兩種資源的基本目的。這就是為什麼我選擇通過簡單地指出基本區別來回答問題,而不是通過列表說“AngularJS使用指令,而jQuery使用CSS選擇器來創建一個jQuery對象來執行此操作等等......” 。這個問題不需要冗長的答案。

jQuery是一種使瀏覽器中的JavaScript編程更容易的方法。更短,跨瀏覽器的命令等

AngularJS擴展了HTML,因此您不必<div>為了創建應用程序而將所有地方放在一起。它使HTML實際上適用於應用程序而不是它的設計目標,即靜態的教育網頁。它使用JavaScript以迂迴的方式實現這一點,但從根本上說它是HTML的擴展,而不是JavaScript。


勢在必行→陳述性

在jQuery中, 選擇器用於查找DOM元素,然後將事件處理程序綁定/註冊到它們。 當事件觸發時,執行(命令性)代碼以更新/更改DOM。

在AngularJS中,您需要考慮視圖而不是DOM元素。 視圖是包含AngularJS 指令的 (聲明性)HTML。 指令為我們幕後設置了事件處理程序,並為我們提供了動態數據綁定。 選擇器很少使用,因此對ID(以及某些類型的類)的需求大大減少。 視圖與模型相關 (通過範圍)。 視圖是模型的投影。 事件更改模型(即數據,範圍屬性)以及投影這些模型的視圖會“自動”更新。

在AngularJS中,考慮模型,而不是jQuery選擇的DOM元素來保存您的數據。 將視圖視為這些模型的投影,而不是註冊回調來操縱用戶看到的內容。

關注點分離

jQuery使用不引人注目的JavaScript - 行為(JavaScript)與結構(HTML)分離。

AngularJS使用控制器和指令(每個控制器和指令可以有自己的控制器和/或編譯和鏈接函數)來從視圖/結構(HTML)中刪除行為。 Angular還提供服務過濾器,以幫助分離/組織您的應用程序。

另請參見https://.com/a/14346528/215945

應用設計

設計AngularJS應用程序的一種方法:

  1. 想想你的模特。 為這些模型創建服務或您自己的JavaScript對象。
  2. 想想你想要如何展示你的模特 - 你的觀點。 為每個視圖創建HTML模板,使用必要的指令來獲取動態數據綁定。
  3. 將控制器連接到每個視圖(使用ng-view和routing,或ng-controller)。 讓控制器只查找/獲取視圖完成其工作所需的任何模型數據。 使控制器盡可能薄。

原型繼承

你可以在不知道JavaScript原型繼承如何工作的情況下使用jQuery做很多事情。 在開發AngularJS應用程序時,如果您對JavaScript繼承有很好的理解,就可以避免一些常見的陷阱。 推薦閱讀: AngularJS中範圍原型/原型繼承的細微差別是什麼?


jQuery是一個DOM操作庫。

AngularJS是一個MV *框架。

事實上,AngularJS是為數不多的JavaScript MV *框架之一(許多JavaScript MVC工具仍屬於類別庫)。

作為一個框架,它託管您的代碼,並擁有決定調用什麼以及何時調用的所有權!

AngularJS本身包含一個jQuery-lite版本。因此,對於一些基本的DOM選擇/操作,您實際上不必包含jQuery庫(它可以節省許多字節以在網絡上運行。)

AngularJS具有用於DOM操作和設計可重用UI組件的“指令”概念,因此您應該在需要執行與DOM操作相關的東西時使用它(指令只是在使用AngularJS時應該編寫jQuery代碼的地方)。

AngularJS涉及一些學習曲線(超過jQuery :-)。

- >對於任何來自jQuery背景的開發人員,我的第一個建議是“在開始使用像AngularJS這樣的豐富框架之前,將JavaScript作為一流語言學習!” 我用艱難的方式了解了上述事實。

祝好運。


為了描述“範式轉換”,我認為一個簡短的回答就足夠了。

AngularJS改變了你找到元素的方式

jQuery中,您通常使用選擇器來查找元素,然後將它們連接起來:
$('#id .class').click(doStuff);

AngularJS中,您可以使用指令直接標記元素,以便將它們連接起來:
<a ng-click="doStuff()">

AngularJS並不需要(或希望)你找到使用選擇元素- AngularJS的之間的主要區別jqLit​​e與全面的jQuery的jqLit​​e不支持選擇

所以當人們說“根本不包含jQuery”時,主要是因為他們不希望你使用選擇器; 他們希望你學習使用指令。直接,不選擇!


jQuery:你對DOM元素的“查詢DOM ”以及做某事有很多想法。

AngularJS:模型是事實,你總是從那個角度思考。

例如,當您從要在DOM中以某種格式顯示的服務器獲取數據時,在jQuery中,您需要'1。找到'你要在DOM中放置這些數據的位置,'2。通過創建新節點或僅設置其innerHTML更新/附加它。然後,當您想要更新此視圖時,您將'3。找到'位置'和'4。UPDATE“。在AngularJS中,在從服務器獲取和格式化數據的相同上下文中完成所有查找和更新循環。

使用AngularJS,您可以獲得模型(已經習慣的JavaScript對象),模型的值會告訴您模型(顯然)和視圖,模型上的操作會自動傳播到視圖,所以你不要我必須考慮一下。你會發現自己在AngularJS中不再在DOM中找到東西。

要以另一種方式,在jQuery中,你需要考慮的CSS選擇器,那就是,哪裡是divtd具有類或屬性,等等,讓我能得到他們的HTML或顏色或價值,但在AngularJS,你會發現自己這樣想:我在處理什麼模型,我會將模型的值設置為true。您不必擔心反映此值的視圖是複選框還是駐留在td元素中(您在jQuery中經常需要考慮的細節)。

在AngularJS中使用DOM操作,您會發現自己添加了指令和過濾器,您可以將其視為有效的HTML擴展。

你將在AngularJS中體驗到的另一件事:在jQuery中你調用jQuery函數很多,在AngularJS中,AngularJS會調用你的函數,所以AngularJS會“告訴你如何做事”,但是它的好處是值得的,所以學習AngularJS通常意味著學習AngularJS想要的東西或者AngularJS要求你展示你的功能的方式,它會相應地調用它。這是使AngularJS成為框架而不是庫的因素之一。


他們是蘋果和橘子。你不想比較它們。他們是兩件不同的事。AngularJs已經內置了jQuery lite,它允許你執行基本的DOM操作,甚至不包括完整的jQuery版本。

jQuery是關於DOM操作的。它解決了所有跨瀏覽器的痛苦,否則你將不得不處理,但它不是一個允許你將你的應用程序劃分為AngularJS等組件的框架。

AngularJs的一個好處是它允許您在指令中分離/隔離DOM操作。有內置指令可供您使用,例如ng-click。您可以創建自己的自定義指令,其中包含所有視圖邏輯或DOM操作,因此您最終不會將DOM操作代碼混合在應該處理業務邏輯的控制器或服務中。

Angular將您的應用分解為 - 控制器 - 服務 - 視圖 - 等

還有一件事,就是指令。它是一個可以附加到任何DOM元素的屬性,你可以在其中使用jQuery,而不必擔心你的jQuery會與AngularJs組件發生衝突或者與它的架構混淆。

我從參加過的聚會中聽到,Angular的一位創始人表示他們非常努力地將DOM操作分開,所以不要試圖將它們包括在內。


實際上,如果您使用的是AngularJS,則不再需要jQuery。AngularJS本身俱有綁定和指令,對於您可以使用jQuery執行的大多數事情來說,這是一個非常好的“替代”。

我通常使用AngularJS和Cordova開發移動應用程序。我需要的jQuery唯一的東西是Selector。

通過谷歌搜索,我看到有一個獨立的jQuery選擇器模塊。這是嘶嘶聲。

我決定製作一個小代碼片段,幫助我使用AngularJS快速啟動一個具有jQuery Selector功能的網站(使用Sizzle)。

我在這里分享了我的代碼:https://github.com/huytd/Sizzularhttps://github.com/huytd/Sizzular


我發現這個問題很有意思,因為我第一次認真接觸JavaScript編程的是Node.js和AngularJS。我從來沒有學過jQuery,我想這是件好事,因為我不需要忘記任何事情。事實上,我主動避免jQuery解決方案來解決我的問題,而只是尋找一種“AngularJS方式”來解決它們。所以,我想我對這個問題的回答基本上歸結為“想像一個從未學過jQuery的人”,並避免任何直接合併jQuery的誘惑(顯然AngularJS在某種程度上在幕後使用它)。





angularjs