AngularJS は、多くの Google 製品で使用されている優れたフロントエンド JS フレームワークです。 AngularJS には多くの機能があり、その最も核となる機能は、MVC、モジュール化、自動双方向データ バインディング、セマンティック タグ、依存関係注入などです。この記事では主にjQueryの使い方とAngularJSのプログラミングアイデアを紹介します。
1. クライアント側の Web アプリケーションを別の方法で設計および設計するにはどうすればよいですか?それらの最大の違いは何ですか? (翻訳者注: jQuery と Angular.js を指します)
2. 何をすべきでないか、何を使用すべきでしょうか?
3. サーバー側の考慮事項/制約はありますか?
私が探しているのは、jQuery と Angular.js の詳細な比較です。
以下は Josh David Miller からのベストアンサーです:
1. 最初にページをデザインしてから DOM 操作を使用して変更しないでください。jQuery では、最初にページをデザインしてから変更します。これは、jQuery がスケールし、ますます肥大化するように設計されているためです。ただし、Angular.js では、最初から「これを持っている」と考える必要はありません。 DOM を実行したいのですが、Angular.js で jQuery を拡張しないでください
同様に、jQuery が X、Y、Z を実行できるという考えから始めないでください。そのため、単に Angular.js を上に追加します。モデルとコントローラーにとっては、最初は誘惑しやすいため、Angular.js の初心者には、少なくとも「Angular のやり方」に慣れるまでは jQuery をまったく使用しないことをお勧めします
私はここにいます (翻訳者注: stackoverflow を指します。) メーリング リストでは、多くの開発者が jQuery プラグイン用に 150 行または 200 行のコードを使用し、混乱を招く複雑なコールバックと $ の束を使用してこれらの複雑なソリューションを構築しているのを見てきました。 Angular.js と貼り付けて適用します。最終的には機能します。ただし、ほとんどの場合、小さな Angular.js コードで jQuery プラグインを書き直すだけで済み、この方法によりすべてがシンプル、明確、理解しやすくなります。この種の問題の結論は、次のとおりです。問題を解決するときは、まず「Angular.js 思考」を使用して解決してください。解決策が思いつかない場合は、次に質問してください。コミュニティ; まだ簡単な解決策がない場合は、自由に jQuery を使用してください。ただし、jqeury を頼りにしないように注意してください。そうでないと、Angular.js を完全にマスターすることはできません
3。アーキテクチャの説明
まず第一に、構造は Web ページではないことを理解する必要があります。したがって、サーバー側の開発者の考え方とクライアント側の開発者の考え方が必要です。アプリケーションを独立したスケーラブルでテスト可能なコンポーネントに分割します
それでは、どうやって「angualrjs の考え方」を使用しますか? 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();
ビューを見るだけで、その機能がすぐにわかります。小規模なアプリケーションの場合はこれで十分です。しかし、大規模なアプリケーションの場合、状況は突然混乱し、保守が困難になります。
しかし、Angular.js では、ビューはビューベースの機能の正式なドキュメントです。私たちの ul は次のように宣言されます:
<ul class="main-menu"dropdown-menu> ... </ul>
どちらも実際には同じことを行いますが、Angular.js バージョンでは、このテンプレートを見れば何が起こるか誰でもわかります。新しい開発者がチームに参加すると、dropdownMenu と呼ばれるディレクティブがビューに適用されていることが一目でわかり、正しい答えを見つけるためにコードを推測したり調べたりする必要はありません。景色そのものが、何が起こるかを教えてくれます。より明確になりました。
angualrjs の初心者はよく次の質問をします: 特定のタイプのすべてのリンクを見つけて、それらにコマンドを追加するにはどうすればよいですか?私の友人たちは私たちの返事を見てショックを受けました。「そんなことは絶対にやめてください。」しかし、私がこれを行わないことをお勧めする理由は、これは半分が jQuery、半分が angulrjs のようなものであり、それは非常に悪いからです。ここでの問題は、開発者が angualrjs コンテキストで jQuery 方法を使用したいことです。そして、これは間違いなくうまくいきません。視聴回数は公式記録です。ディレクティブの範囲外で DOM を変更しないでください (これについては後述します)。しかもその指示はビューに反映されており、当然目的も明確です。
覚えておいてください: 最初にデザインしてからレタッチしないでください。まず設計を行い、次にデザインについて考える必要があります。
データ バインディング
これは現在 Angular.js の最も優れた機能の 1 つであり、前述した必要な DOM 操作をすべて即座に強制終了します。自分で行う必要はありません。Angular.js がビューを自動的に更新します!
在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来测试逻辑呢?还有,如果我们希望改变展现呢?
真是让人凌乱。。。
但是在Angular.js中,我们可以这样做:
$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有点像模型。但是在angualrjs中,我们有一个分离的模型层, 而这个模型层可以让我们用任何方式管理,完全独立于视图。这对于上面说的数据绑定很有帮助, 还可以维护关注点分离,并且引入更多的可测试性。其它的答案提到了这点,所以我这里就不再赘述了。
关注点分离
以上所有的这些把我们带入了这样的主题:保持你的关注点分离。你的视图表现的像记录什么会发生(大部分情况)的正式记录;你的模型表现你的数据;你有一个服务层来执行可重用的任务;你执行dom操作并通过指令扩展你的视图;并且你用控制器来组合这些。这些同样已经在其它答案中提到,我在这里唯一还要提出的一个事情就是可测试性,我会在下文的另一节里专门讨论。
依赖注入
依赖注入是让我们实现关注点分离的方法。如果你是一个服务器端的开发者(从java到php),你可能对这个概念已经非常熟悉了,但是如果你是一个来自jQuery的客户端的朋友,那么你可能会认为这个概念是傻浅挫。但是它可不是:)
从一个更广的观点来看, 依赖注入意味着你可以非常自由的声明组件,然后你可以通过任意其它组件,呼叫一个它的实例,然后授权。
你不需要知道载入顺序,或者文件位置,或者其它类似的东西。这种强大的力量可能不会立刻显现,但是我这里会提供一个(通常)的例子:测试。
比如在我们的应用中,需要一个通过REST API,同时也依赖于应用状态,本地存储实现了服务器端存储的服务。当在我们的控制器上跑测试的时候,我们不希望与服务器端通讯-毕竟我们在测试控制器。我们能够仅仅添加一个与我们原始组件同名的mock服务,注入器将确保我们的控制器自动获取伪造对象–我们的控制器不会也不需要知道它们的区别。
那么既然提到测试……
4. 保持测试驱动的开发
这个其实是关于架构的第三节的一部分,但是这个主题非常重要,所以我需要将其提出来作为自成体系的部分。
那些你看过,用过,写过的所有jQuery插件,它们中有多少有相应的测试包?不是很多吧? 因为jQuery可不是很遵守这个规矩。但是angualrjs是。
在jQuery中, 测试的唯一方法是用示例页面来独立地创建组件,针对该页面我们的测试可以实施dom操作。于是我们就不得不分离地开发一个组件然后将其集成进我们的应用。多么不方便啊!
那么多时间啊,当我们使用jQuery开发时,我们选择使用迭代开发代替测试驱动的开发。可以谁又能怪我们呢?
但是因为我们有关注点分离,我们能够在Angular.js里反复使用测试驱动开发。举个例子,我们想要一个超简单的指令来指示在菜单中我们目前的路径是什么。我们可以在视图中这样声明我们想获取的:
<a href="/hello"when-active>Hello</a>
好了,我们现在可以写个测试:
it( 'should add "active" when the route changes', inject(function() { varelm = $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'); } }); } }; });
现在我们的测试通过了,并且我们的菜单按照请求运行。我们的开发是迭代并且测试驱动的,太酷了哦!
5. 从概念上来看,指令不是打包的jQuery
你会经常听到“只在指令里做dom操作”。这是必要的。请对它表示出尊重!
但是让我们谈点更深入的。。。
一些指令只是装饰那些在视图里的已有的(想想ngClass),因此有时候就直接进行dom操作,基本上都能搞定。但是如果一个指令像个“widget”并有一个模板,
那它同样要遵守关注点分离原则。也就是说,这个模板也应该与它在链接和控制器函数里的实现保持最大的独立。
Angular.js自带着一套工具让这件事变得简单; 使用ngClass我们能够动态的更新类;ngBind允许双向的数据绑定;ngShow和ngHide以编程的方式显示或隐藏一个元素;还有更多–包括我们自己写的那些。换句话说, 我们可以不用DOM操作来实现所有的酷炫的事儿。 dom操作越少,指令越容易测试,它们也更容易样式化,在未来它们也更容易改变,并且也变得更加可重用和可分发。
我看到很多Angular.js开发新手将指令当做放置一堆jQuery的地方。换句话说, 他们认为:“既然我不能在控制器里做dom操纵,那么我就把这段代码放到指令里”。当然这看上去好多了,但是通常这仍然是错的。
想一下在第三节里我们编写的日志记录。即使我们将其放到一个指令里,我们仍然希望用“anggualjs方式”来做这件事情。这仍然没有做任何dom操作!在很多情况下dom操作是必须的,但是这种情况其实比你想的少得多!在你在你的应用中到处使用dmo操作之前,问问你自己,这真的是必须的吗。可能有更好的方法呢。
这里用一个简单的例子来展示我们经常会看到的一个模式。我们需要一个切换按钮。(注意:这个例子有那么一点人为设计的技巧并且有点啰嗦,但是很多更复杂的情况其实也完全可以根据这个例子的方式来解决。)
.directive( 'myDirective',function() { return{ template:'<a class="btn">Toggle me!</a>', link:function( scope, element, attrs ) { varon =false; $(element).click(function() { if( on ) { $(element).removeClass('active'); } else{ $(element).addClass('active'); } on = !on; }); } }; });
这里有一些错误。第一,jQuery不是必须的。我们这里做的一切都不需要jQuery!第二, 即使是我们的页面上已经有jQuery,也没有理由一定要在这里使用它;我们可以简单的使用angular.element,而且就算在一个没有jQuery的项目中我们的组件仍然可以工作。第三,即使我们假设为了让这个指令工作,jQuery是必须的,如果jqury被加载,那么jqLite(angler.element)一定会使用jQuery。所以我们不需要使用$(译者注:jQuery的一个标识符号,是jQuery函数的别名)–我们可以使用angular.element。第四, 紧接第三点,jqLite元素不需要被包裹在$里–传递给link函数的element已经是一个jQuery元素!第五, 我上一节已经提过的,为什么我们要将模板混合进我们的逻辑呢?
这个指令可以更精简的重写(即时在更复杂的例子里也一样):
.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绝不会被接触,所以重构就变得容易。你可以在不接触指令的情况下随意改变你的模板。并且不论你怎么变,你的测试仍可以通过。
耶!
所以如果指令不只是一组jQuery风格的函数,那么它们是什么呢?指令其实就是html的扩展。如果html不能完成你希望它做的一些事情,你就写一个指令来做,并且当它是html的一部分来使用。
换句话说, 如果Angular.js一下子无法完成手头的工作,想想看你的团队是否能用ngClick、ngClass等来搞定它。
以上内容主要是关于会jQuery,该如何用AngularJS编程思想,希望对大家有帮助。
相关推荐:
以上がAngularJS プログラミングのアイデアの使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。