国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
StackOverFlow精彩問(wèn)答賞析:有jQuery背景的開(kāi)發(fā)者如何建立起AngularJS的思維模式?

1. 不要先設(shè)計(jì)頁(yè)面,然后再使用DOM操作來(lái)改變它的展現(xiàn)

在jQuery中,你通常會(huì)設(shè)計(jì)一個(gè)頁(yè)面,然后再給它動(dòng)態(tài)效果。這是因?yàn)閖Query的設(shè)計(jì)就是為了擴(kuò)充DOM并在這個(gè)簡(jiǎn)單的前提下瘋狂的生長(zhǎng)的。

但是在AngularJS里,必須從頭開(kāi)始就在頭腦中思考架構(gòu)。必須從你想要完成的功能開(kāi)始,然后設(shè)計(jì)應(yīng)用程序,最后來(lái)設(shè)計(jì)視圖,而非“我有這么一個(gè)DOM片段,我想讓他可以實(shí)現(xiàn)XXX效果”。

2. 不要用AngularJS來(lái)加強(qiáng)jQuery

類(lèi)似的,不要以這樣的思維開(kāi)始:用jQuery來(lái)做X,Y和Z,然后只需要把AngularJS的models和controllers加在這上面。這在剛開(kāi)始的時(shí)候顯得非常誘人,這也是為什么我總是建議AngularJS的新手完全不使用jQuery,至少不要在習(xí)慣使用“Angular Way”開(kāi)發(fā)之前這么做。

我在郵件列表里看到很多開(kāi)發(fā)者使用150或200行代碼的jQuery插件創(chuàng)造出這些復(fù)雜的解決方案,然后使用一堆callback函數(shù)以及$apply把它粘合到AngularJS里,看起來(lái)復(fù)雜難懂;但是他們最終還是把它搞定了!問(wèn)題是在大多數(shù)情況下這些jQuery插件可以使用很少的AngularJS代碼重寫(xiě),而且所有的一切都很簡(jiǎn)單直接容易理解。

這里的底線是:當(dāng)你選擇解決方案時(shí),首先“think in AngularJS”;如果想不出一個(gè)解決方案,去社區(qū)求助;如果還是沒(méi)有簡(jiǎn)單的解決方案,再考慮使用jQuery。但是不要讓jQuery成為你的拐杖,導(dǎo)致你永遠(yuǎn)無(wú)法真正掌握AngularJS。

3. 總是以架構(gòu)的角度思考

首先要知道Single-page應(yīng)用是應(yīng)用,不是網(wǎng)頁(yè)。所以我們除了像一個(gè)客戶端開(kāi)發(fā)者般思考外,還需要像一個(gè)服務(wù)器端開(kāi)發(fā)者一樣思考。我們必須考慮如何把我們的應(yīng)用分割成獨(dú)立的,可擴(kuò)展且可測(cè)試的組件。

那么如何做到呢?如何“think in AngularJS”?這里有一些基本原則,對(duì)比jQuery。

視圖是“Official Record”

在jQuery里,我們編程改變視圖。我們會(huì)將一個(gè)下拉菜單定義為一個(gè)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里,我們會(huì)在應(yīng)用邏輯里這樣啟用這個(gè)下拉菜單:

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

當(dāng)我們只關(guān)注視圖,這里不會(huì)立即明顯的體現(xiàn)出任何(業(yè)務(wù))功能。對(duì)于小型應(yīng)用,這沒(méi)什么不妥。但是在規(guī)模較大的應(yīng)用中,事情就會(huì)變得難以理解且難以維護(hù)。

而在AngularJS里,視圖是基于視圖的功能。ul聲明就會(huì)像這樣:

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

這兩種方式做了同樣的東西,但是在AngularJS的版本里任何人看到這個(gè)模版都可以知道將會(huì)發(fā)生什么事。不論何時(shí)一個(gè)新成員加入開(kāi)發(fā)團(tuán)隊(duì),他看到這個(gè)就會(huì)知道有一個(gè)叫做dropdownMenu的directive作用在這個(gè)標(biāo)簽上;他不需要靠直覺(jué)去猜測(cè)代碼的功能或者去看任何代碼。視圖本身告訴我們會(huì)發(fā)生什么事。清晰多了。

首次接觸AngularJS的開(kāi)發(fā)者通常會(huì)問(wèn)這樣一個(gè)問(wèn)題:如何找到所有的某類(lèi)元素然后給它們加上一個(gè)directive。但當(dāng)我們告訴他:別這么做時(shí),他總會(huì)顯得非常的驚愕。而不這么做的原因是這是一種半jQuery半AngularJS的方式,這么做不好。這里的問(wèn)題在于開(kāi)發(fā)者嘗試在 AngularJS的環(huán)境里“do jQuery”。這么做總會(huì)有一些問(wèn)題。視圖是official record(譯者注:作者可能想表達(dá)視圖是一等公民)。在一個(gè)directive外,絕不要改變DOM。所有的directive都應(yīng)用在試圖上,意圖非常清晰。

記?。翰灰O(shè)計(jì),然后寫(xiě)標(biāo)簽。你需要架構(gòu),然后設(shè)計(jì)。

數(shù)據(jù)綁定

這是到現(xiàn)在為止最酷的AngularJS特性。這個(gè)特性使得前面提到的很多DOM操作都顯得不再需要。AngularJS會(huì)自動(dòng)更新視圖,所以你自己不用這么做!在jQuery里,我們響應(yīng)事件然后更新內(nèi)容,就像這樣:

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

對(duì)應(yīng)的視圖:

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

除了要考慮多個(gè)方面,我們也會(huì)遇到前面視圖中的問(wèn)題。但是更重要的是,需要手動(dòng)引用并更新一個(gè)DOM節(jié)點(diǎn)。如果我們想要?jiǎng)h除一個(gè)log條目,也需要針對(duì)DOM編碼。那么如何脫離DOM來(lái)測(cè)試這個(gè)邏輯?如果想要改變展現(xiàn)形式怎么辦?

這有一點(diǎn)凌亂瑣碎。但是在AngularJS里,可以這樣來(lái)實(shí)現(xiàn):

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

視圖看起來(lái)是這個(gè)樣子的:

<ul class="messages"> <li ng-repeat="entry in log"></li> </ul>

但是其實(shí)還可以這樣來(lái)做:

<div class="messages"> <div class="alert" ng-repeat="entry in log">  </div> </div>

現(xiàn)在如果我們想使用Bootstrap的alert boxes,而不是一個(gè)無(wú)序列表,根本不需要改變?nèi)魏蔚腸ontroller代碼!更重要的是,不論log在何處或如何被更新,視圖便會(huì)隨之更新。自動(dòng)的。巧妙!

盡管我沒(méi)有在這里展示,數(shù)據(jù)綁定其實(shí)是雙向的。所以這些log信息在視圖里也可以是可編輯的。只需要這么做:

<input ng-model="entry.msg" />

。簡(jiǎn)單快樂(lè)。

清晰的模型(Model)層

在jQuery里,DOM在一定程度上扮演了模型的角色。但在AngularJS中,我們有一個(gè)獨(dú)立的模型層可以靈活的管理。完全與視圖獨(dú)立。這有助于上述的數(shù)據(jù)綁定,維護(hù)了關(guān)注點(diǎn)的分離(獨(dú)立的考慮視圖和模型),并且引入了更好的可測(cè)性。后面還會(huì)提到這點(diǎn)。

關(guān)注點(diǎn)分離

上面所有的內(nèi)容都與這個(gè)愿景相關(guān):保持你的關(guān)注點(diǎn)分離。視圖負(fù)責(zé)展現(xiàn)將要發(fā)生的事情;模型表現(xiàn)數(shù)據(jù);有一個(gè)service層來(lái)實(shí)現(xiàn)可復(fù)用的任務(wù);在 directive里面進(jìn)行DOM操作和擴(kuò)展;使用controller來(lái)把上面的東西粘合起來(lái)。這在其他的答案里也有敘述,我在這里只增加關(guān)于可測(cè)試性的內(nèi)容,在后面的一個(gè)段落里詳述。

依賴注入

依賴注入幫我們實(shí)現(xiàn)了關(guān)注點(diǎn)分離。如果你來(lái)自一個(gè)服務(wù)器語(yǔ)言(java或php),可能對(duì)這個(gè)概念已經(jīng)非常熟悉,但是如果你是一個(gè)來(lái)自jQuery的客戶端開(kāi)發(fā)者,這個(gè)概念可能看起來(lái)有點(diǎn)傻而多余。但其實(shí)不是的。。。

大體來(lái)講,DI意味著可以非常自由的聲明組件,然后在另一個(gè)組件里,只需要請(qǐng)求一個(gè)該組件的實(shí)例,就可以得到它。不需要知道(關(guān)心)加載順序,或者文件位置,或類(lèi)似的事情。這種強(qiáng)大可能不會(huì)立刻顯現(xiàn),但是我只提供一個(gè)(常見(jiàn)。。)的例子:測(cè)試。

就說(shuō)在你的應(yīng)用里,我們需要一個(gè)服務(wù)通過(guò)REST API來(lái)實(shí)現(xiàn)服務(wù)器端存儲(chǔ),并且根據(jù)不同的應(yīng)用狀態(tài),也有可能使用(客戶端)本地存儲(chǔ)。當(dāng)我們運(yùn)行controller的測(cè)試時(shí),不希望必須和服務(wù)器交互 —— 畢竟是在測(cè)試controller邏輯。我們可以只添加一個(gè)與本來(lái)使用的service同名的mock service,injector會(huì)確保controller自動(dòng)得到假的那個(gè)service —— controller不會(huì)也不需要知道有什么不同。

說(shuō)起測(cè)試……

4. 總是 —— 測(cè)試驅(qū)動(dòng)開(kāi)發(fā)

這其實(shí)是關(guān)于架構(gòu)的第3節(jié)。但是它太重要了,所以我把它單獨(dú)拿出來(lái)作為一個(gè)頂級(jí)段落。

在所有那些你見(jiàn)過(guò),用過(guò)或?qū)戇^(guò)的jQuery插件中,有多少是有測(cè)試集的?不多,因?yàn)閖Query經(jīng)不起測(cè)試的考驗(yàn)。但是AngularJS可以。

在jQuery中,唯一的測(cè)試方式通常是獨(dú)立地創(chuàng)建附帶sample/demo頁(yè)面的組件,然后我們的測(cè)試在這個(gè)頁(yè)面上做DOM操作。所以我們必須獨(dú)立的開(kāi)發(fā)一個(gè)組件,然后集成到應(yīng)用里。多不方便!在使用jQuery開(kāi)發(fā)時(shí),太多的時(shí)間,我們挑選迭代而非測(cè)試驅(qū)動(dòng)開(kāi)發(fā)。誰(shuí)又能責(zé)怪我們呢?

但是因?yàn)橛辛岁P(guān)注點(diǎn)分離,我們可以在AngularJS中迭代地做測(cè)試驅(qū)動(dòng)開(kāi)發(fā)!例如,想要一個(gè)超級(jí)簡(jiǎn)單的directive來(lái)展現(xiàn)我們的當(dāng)前路徑??梢栽谝晥D里聲明:

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

OK,現(xiàn)在可以寫(xiě)一個(gè)測(cè)試:

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();}));

執(zhí)行這個(gè)測(cè)試來(lái)確認(rèn)它是失敗的。然后我們可以開(kāi)始寫(xiě)這個(gè)directive了:

.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');                }            });        }    };});

測(cè)試現(xiàn)在通過(guò)了,然后我們的menu按照請(qǐng)求的方式執(zhí)行。開(kāi)發(fā)過(guò)程既是迭代的也是測(cè)試驅(qū)動(dòng)的。太酷了。

5. 概念上,Directives并不是打包的jQuery

你經(jīng)常會(huì)聽(tīng)到“只在directive里做DOM操作”。這是必需的。請(qǐng)給它應(yīng)有的尊重!

但讓我們?cè)偕钊胍稽c(diǎn)……

一些directive僅僅裝飾了視圖中已經(jīng)存在的東西(想想ngClass)并且因此有時(shí)候僅僅直接做完DOM操作然后就完事了。但是如果一個(gè) directive像一個(gè)“widget”并且有一個(gè)模版,那么它也要做到關(guān)注點(diǎn)分離。也就是說(shuō),模版本身也應(yīng)該很大程度上與其link和 controller實(shí)現(xiàn)保持獨(dú)立。

AngularJS擁有一整套工具使這個(gè)過(guò)程非常簡(jiǎn)單;有了ngClass我們可以動(dòng)態(tài)地更新class;ngBind使得我們可以做雙向數(shù)據(jù)綁定。ngShow和ngHide可編程地展示和隱藏一個(gè)元素;以及更多地 —— 包括那些我們自己寫(xiě)的。換句話說(shuō),我們可以做到任何DOM操作能實(shí)現(xiàn)的特性。DOM操作越少,directive就越容易測(cè)試,也越容易給它們添加樣式,在未來(lái)也越容易擁抱變化,并且更加的可復(fù)用和發(fā)布。

我見(jiàn)過(guò)很多AngularJS新手,把一堆jQuery扔到directive里。換句話說(shuō),他們認(rèn)為“因?yàn)椴荒茉赾ontroller里做DOM操作,就把那些代碼弄到directive里好了”。雖然這么做確實(shí)好一些,但是依然是錯(cuò)誤的。

回想一下我們?cè)诘?節(jié)里寫(xiě)的那個(gè)logger。即使要把它放在一個(gè)directive里,我們依然希望用“Angular Way”來(lái)做。它依然沒(méi)有任何DOM操作!有很多時(shí)候DOM操作是必要的,但其實(shí)比你想的要少得多!在應(yīng)用里的任何地方做DOM操作之前,問(wèn)問(wèn)你自己是不是真的需要這么做。有可能有更好的方式。

這里有一個(gè)示例,展示出了我見(jiàn)過(guò)最多的一種模式。我們想做一個(gè)可以toggle的按鈕。(注意:這個(gè)例子有一點(diǎn)牽強(qiáng)、啰嗦,這是為了表達(dá)出使用同樣方式處理問(wèn)題的更復(fù)雜的情況。)

.directive('myDirective', function () {    return {        template: '<a class="btn">Toggle me!</a>',        link: function (scope, element, attrs) {            var on = false;            $(element).click(function () {                if (on) {                    $(element).removeClass('active');                } else {                    $(element).addClass('active');                }                on = !on;            });        }    };});

這里有一些錯(cuò)誤的地方。首先,jQeury根本沒(méi)必要出現(xiàn)。我們?cè)谶@里做的事情都根本用不著jQuery!其次,即使已經(jīng)將jQuery用在了頁(yè)面上,也沒(méi)有理由用在這里。第三,即使假設(shè)這個(gè)directive依賴jQuery來(lái)工作,jqLite(angular.element)在加載后總會(huì)使用jQuery!所以我們沒(méi)必要使用$ —— 用angular.element就夠了。第四,和第三條緊密關(guān)聯(lián),jqLite元素不需要被$封裝 —— 傳到link里的元素本來(lái)就會(huì)是一個(gè)jQuery元素!第五,我們?cè)谇懊娑温渲姓f(shuō)過(guò),為什么要把模版的東西混到邏輯里?

這個(gè)directive可以(即使是更復(fù)雜的情況下?。?xiě)得更簡(jiǎn)單:

.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;            };        }    };});

再一次地,模版就在模版里,當(dāng)有樣式需求時(shí),你(或你的用戶)可以輕松的換掉它,不用去碰邏輯。重用性 —— boom!

當(dāng)然還有其他的好處,像測(cè)試 —— 很簡(jiǎn)單!不論模版中有什么,directive的內(nèi)部API從來(lái)不會(huì)被碰到,所以重構(gòu)也很容易。可以不碰directive就做到任意改變模版。不論你怎么改,測(cè)試總是通過(guò)的。

所以如果directive不僅僅是一組類(lèi)似jQuery的函數(shù),那他們是什么?Directive實(shí)際是HTML的擴(kuò)展。如果HTML沒(méi)有做你需要它做的事情,你就寫(xiě)一個(gè)directive來(lái)實(shí)現(xiàn),然后就像使用HTML一樣使用它。

換句話說(shuō),如果AngularJS庫(kù)沒(méi)有做的一些事情,想想開(kāi)發(fā)團(tuán)隊(duì)會(huì)如何完成它來(lái)配合ngClick,ngClass等。

總結(jié)

不要用jQuery。連include也不要。它會(huì)讓你停滯不前。如果遇到一個(gè)你認(rèn)為已經(jīng)知道如何使用jQuery來(lái)解決的問(wèn)題,在使用$之前,試試想想如何在AngularJS的限制下解決它。如果你不知道,問(wèn)!20次中的19次,最好的方式不需要jQuery。如果嘗試使用jQuery會(huì)增加你的工作量。


這是我目前最長(zhǎng)的Stack Overflow回答。事實(shí)上,這個(gè)答案太長(zhǎng)了,我都要填一個(gè)Captcha了。但是就如我常說(shuō)的:能說(shuō)多時(shí)候說(shuō)的少其實(shí)就是懶。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
jQuery和AngularJS的區(qū)別淺析
AngularJS 、Backbone.js 和 Ember.js 的比較
12種jQuery代碼性能優(yōu)化方法 | 銳博
jQuery性能優(yōu)化
對(duì)比Jquery和Vue實(shí)現(xiàn)Todolist
關(guān)于 AngularJS 框架的使用有哪些經(jīng)驗(yàn)值得分享? |
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服