AngularJS is an excellent front-end JS framework that has been used in many Google products. AngularJS has many features, the most core of which are: MVC, modularization, automated two-way data binding, semantic tags, dependency injection, etc. In this article, we mainly share with you how to use jQuery and how to use AngularJS programming ideas.
1. How can I architect and design client-side web applications differently? What's the biggest difference between them? (Translator's Note: Refers to jQuery and Angular.js)
2. What should I not do or use? And what should I do or use?
3. Are there any server-side considerations/constraints?
What I'm looking for is a detailed comparison between jQuery and Angular.js. ”
The following is the best answer from Josh David Miller:
1. Never design your page first and then use DOM manipulation to change it
In jQuery , you would design a page first and then make it dynamic. This is because jQuery is designed to be extensible and becomes more and more bloated under this premise
But in Angular.js. , you have to have the architecture in mind from the beginning. Instead of thinking "I have a DOM like this and I want it to do X", you have to start thinking about what you want to accomplish, and then. Design your application, and finally your views.
2. Don’t extend jQuery with Angular.js
Similarly, don’t start with the idea that jQuery can do it. X, Y, Z, so I just add Angular.js on top of it for models and controllers. It's really easy to seduce you in the beginning, which is why I always recommend that newbies to Angular.js don't use jQuery at all, At least after they get used to the "angular way"
I've seen many developers here (Translator's Note: referring to stackoverflow) and on the mailing list, who use jQuery plug-ins with 150 or 200 lines of code. , and then use a confusing bunch of callbacks and $apply to glue together with Angular.js to build these elaborate solutions; it finally works! But in most cases, this problem can be solved in a short paragraph. Just rewrite the jQuery plug-in with Angular.js code, and this method will make everything simple, clear and understandable in an instant
I think the bottom line for this kind of problem is: when you solve the problem, first use it. "Angular.js thinking" do it; if you can't come up with a solution, then ask in the community; if there is still no easy solution, then feel free to use jQuery. But be careful, don't let jqeury be you. crutch, otherwise you will never truly master Angular.js
3. Always think in terms of architecture
First of all, you must know that a single-page structure is also an application, so we are. We need server-side developer thinking plus client-side developer thinking. We must think about how to split our applications into independent, scalable, and testable components.
So what do you do? How to use "angualrjs thinking"? Here are some general principles, compared with jQuery
Views are "official records"
In jQuery, we change it programmatically. View. We can define a drop-down menu through the ul tag as follows:
<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>
In jQuery, according to the logic we apply, we can activate it with a statement similar to the following.
$('.main-menu').dropdownMenu();
When we just look at a view, we don't immediately see its functionality. For small applications, this is fine. But for large applications, the situation suddenly becomes confusing and difficult to maintain.
But in Angular.js, a view is a formal record of view-based functionality. Our ul is declared like this:
<ul class="main-menu"dropdown-menu> ... </ul>
These two actually do the same thing, but in the Angular.js version, anyone who sees this template knows what is going to happen. Whenever a new developer joins the team, she can see at a glance that a directive called dropdownMenu is applied to the view; she doesn't have to guess or study code to find the right answer. The view itself tells us what will happen. Much clearer.
Newbies to angualrjs often ask this question: How do I find all links of a certain type and add a command to them? My friends were shocked when they saw our reply: Don't do this at all. But the reason I advise you not to do this is that it's like half jQuery, half angulrjs, and that's really bad. The problem here is that the developer wants to use jQuery way in angualrjs context. And this is definitely not going to work. Views are official records. You should never change the DOM outside the scope of the directive (more on this below). Moreover, the instructions are applied in the view, and the purpose is naturally clear.
Remember: Don’t design first and then modify. You have to architect first and think about design second.
Data binding
This is one of the coolest features of Angular.js currently, and it instantly kills all the required DOM operations I mentioned earlier. No need for you to do it yourself, Angular.js will automatically update your views!
在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编程思想,希望对大家有帮助。
相关推荐:
The above is the detailed content of How to use AngularJS programming ideas. For more information, please follow other related articles on the PHP Chinese website!