具备 jQuery 经验的人如何学习AngularJS(附:学习路径)
这是一个来自stackoverflow的问答,三哥直接把最佳回答搬过来了。
都说AngularJS的学习曲线异常诡异~~~
Q:
“Thinking in AngularJS” if I have a jQuery background?
A:
1. Don't design your page, and then change it with DOMmanipulations
In jQuery, you design a page, and then you make it dynamic. This is because jQuery was designed for augmentation and has grown incredibly from that simple premise.
But in AngularJS, you must start from the ground up with your architecture in mind. Instead of starting by thinking "I have this piece of the DOM and I want to make it do X", you have to start with what you want to accomplish, then go about designing your application, and then finally go about designing your view.
2. Don't augment jQuery with AngularJS
Similarly, don't start with the idea that jQuery does X, Y, and Z, so I'll just add AngularJS on top of that for models and controllers. This is really tempting when you're just starting out, which is why I always recommend that new AngularJS developers don't use jQuery at all, at least until they get used to doing things the "Angular Way".
I've seen many developers here and on the mailing list create these elaborate solutions with jQuery plugins of 150 or 200 lines of code that they then glue into AngularJS with a collection of callbacks and$applys that are confusing and convoluted; but they eventually get it working! The problem is that in most cases that jQuery plugin could be rewritten in AngularJS in a fraction of the code, where suddenly everything becomes comprehensible and straightforward.
The bottom line is this: when solutioning, first "think in AngularJS"; if you can't think of a solution, ask the community; if after all of that there is no easy solution, then feel free to reach for the jQuery. But don't let jQuery become a crutch or you'll never master AngularJS.
3. Always think in terms of architecture
First know that single-page applications are applications. They're not webpages. So we need to think like a server-side developer in addition to thinking like a client-side developer. We have to think about how to divide our application into individual, extensible, testable components.
So then how do you do that? How do you "think in AngularJS"? Here are some general principles, contrasted with jQuery.
The view is the "official record"
In jQuery, we programmatically change the view. We could have a dropdown menu defined as a ullike so:
<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, in our application logic, we would activate it with something like:
$('.main-menu').dropdownMenu();
When we just look at the view, it's not immediately obvious that there is any functionality here. For small applications, that's fine. But for non-trivial applications, things quickly get confusing and hard to maintain.
In AngularJS, though, the view is the official record of view-based functionality. Our ul declaration would look like this instead:
<ul class="main-menu" dropdown-menu>
...
</ul>
These two do the same thing, but in the AngularJS version anyone looking at the template knows what's supposed to happen. Whenever a new member of the development team comes on board, she can look at this and then know that there is a directive called dropdownMenu operating on it; she doesn't need to intuit the right answer or sift through any code. The view told us what was supposed to happen. Much cleaner.
Developers new to AngularJS often ask a question like: how do I find all links of a specific kind and add a directive onto them. The developer is always flabbergasted when we reply: you don't. But the reason you don't do that is that this is like half-jQuery, half-AngularJS, and no good. The problem here is that the developer is trying to "do jQuery" in the context of AngularJS. That's never going to work well. The view is the official record. Outside of a directive (more on this below), you never, ever, neverchange the DOM. And directives are applied in the view, so intent is clear.
Remember: don't design, and then mark up. You must architect, and then design.
Data binding
This is by far one of the most awesome features of AngularJS and cuts out a lot of the need to do the kinds of DOM manipulations I mentioned in the previous section. AngularJS will automatically update your view so you don't have to! In jQuery, we respond to events and then update content. Something like:
$.ajax({
url: '/myEndpoint.json',
success: function ( data, status ) {
$('ul#log').append('<li>Data Received!</li>');
}
});
For a view that looks like this:
<ul class="messages" id="log">
</ul>
Apart from mixing concerns, we also have the same problems of signifying intent that I mentioned before. But more importantly, we had to manually reference and update a DOM node. And if we want to delete a log entry, we have to code against the DOM for that too. How do we test the logic apart from the DOM? And what if we want to change the presentation?
This a little messy and a trifle frail. But in AngularJS, we can do this:
$http( '/myEndpoint.json' ).then( function ( response ) {
$scope.log.push( { msg: 'Data Received!' } );
});
And our view can look like this:
<ul class="messages">
<li ng-repeat="entry in log">{{ entry.msg }}</li>
</ul>
But for that matter, our view could look like this:
<div class="messages">
<div class="alert" ng-repeat="entry in log">
{{ entry.msg }}
</div>
</div>
And now instead of using an unordered list, we're using Bootstrap alert boxes. And we never had to change the controller code! But more importantly, no matter where or how the log gets updated, the view will change too. Automatically. Neat!
Though I didn't show it here, the data binding is two-way. So those log messages could also be editable in the view just by doing this: <input ng-model="entry.msg" />. And there was much rejoicing.
Distinct model layer
In jQuery, the DOM is kind of like the model. But in AngularJS, we have a separate model layer that we can manage in any way we want, completely independently from the view. This helps for the above data binding, maintains separation of concerns, and introduces far greater testability. Other answers mentioned this point, so I'll just leave it at that.
Separation of concerns
And all of the above tie into this over-arching theme: keep your concerns separate. Your view acts as the official record of what is supposed to happen (for the most part); your model represents your data; you have a service layer to perform reusable tasks; you do DOM manipulation and augment your view with directives; and you glue it all together with controllers. This was also mentioned in other answers, and the only thing I would add pertains to testability, which I discuss in another section below.
Dependency injection
To help us out with separation of concerns is dependency injection (DI). If you come from a server-side language (from Java to PHP) you're probably familiar with this concept already, but if you're a client-side guy coming from jQuery, this concept can seem anything from silly to superfluous to hipster. But it's not. :-)
From a broad perspective, DI means that you can declare components very freely and then from any other component, just ask for an instance of it and it will be granted. You don't have to know about loading order, or file locations, or anything like that. The power may not immediately be visible, but I'll provide just one (common) example: testing.
Let's say in our application, we require a service that implements server-side storage through a RESTAPI and, depending on application state, local storage as well. When running tests on our controllers, we don't want to have to communicate with the server - we're testing the controller, after all. We can just add a mock service of the same name as our original component, and the injector will ensure that our controller gets the fake one automatically - our controller doesn't and needn't know the difference.
Speaking of testing...
4. Test-driven development - always
This is really part of section 3 on architecture, but it's so important that I'm putting it as its own top-level section.
Out of all of the many jQuery plugins you've seen, used, or written, how many of them had an accompanying test suite? Not very many because jQuery isn't very amenable to that. But AngularJS is.
In jQuery, the only way to test is often to create the component independently with a sample/demo page against which our tests can perform DOM manipulation. So then we have to develop a component separately and then integrate it into our application. How inconvenient! So much of the time, when developing with jQuery, we opt for iterative instead of test-driven development. And who could blame us?
But because we have separation of concerns, we can do test-driven development iteratively in AngularJS! For example, let's say we want a super-simple directive to indicate in our menu what our current route is. We can declare what we want in the view of our application:
<a href="/hello" when-active>Hello</a>
Okay, now we can write a test for the non-existent when-active directive:
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();
}));
And when we run our test, we can confirm that it fails. Only now should we create our 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' );
}
});
}
};
});
Our test now passes and our menu performs as requested. Our development is both iterative andtest-driven. Wicked-cool.
5. Conceptually, directives are not packaged jQuery
You'll often hear "only do DOM manipulation in a directive". This is a necessity. Treat it with due deference!
But let's dive a little deeper...
Some directives just decorate what's already in the view (think ngClass) and therefore sometimes do DOM manipulation straight away and then are basically done. But if a directive is like a "widget" and has a template, it should also respect separation of concerns. That is, the template too should remain largely independent from its implementation in the link and controller functions.
AngularJS comes with an entire set of tools to make this very easy; with ngClass we can dynamically update the class; ngModel allows two-way data binding; ngShow and ngHideprogrammatically show or hide an element; and many more - including the ones we write ourselves. In other words, we can do all kinds of awesomeness without DOM manipulation. The less DOM manipulation, the easier directives are to test, the easier they are to style, the easier they are to change in the future, and the more re-usable and distributable they are.
I see lots of developers new to AngularJS using directives as the place to throw a bunch of jQuery. In other words, they think "since I can't do DOM manipulation in the controller, I'll take that code put it in a directive". While that certainly is much better, it's often still wrong.
Think of the logger we programmed in section 3. Even if we put that in a directive, we still want to do it the "Angular Way". It still doesn't take any DOM manipulation! There are lots of times when DOM manipulation is necessary, but it's a lot rarer than you think! Before doing DOM manipulationanywhere in your application, ask yourself if you really need to. There might be a better way.
Here's a quick example that shows the pattern I see most frequently. We want a toggleable button. (Note: this example is a little contrived and a skosh verbose to represent more complicated cases that are solved in exactly the same way.)
.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);
});
}
};
});
There are a few things wrong with this:
- First, jQuery was never necessary. There's nothing we did here that needed jQuery at all!
- Second, even if we already have jQuery on our page, there's no reason to use it here; we can simply use
angular.elementand our component will still work when dropped into a project that doesn't have jQuery. - Third, even assuming jQuery was required for this directive to work, jqLite (
angular.element) will always use jQuery if it was loaded! So we needn't use the$- we can just useangular.element. - Fourth, closely related to the third, is that jqLite elements needn't be wrapped in
$- theelementthat is passed to thelinkfunction would already be a jQuery element! - And fifth, which we've mentioned in previous sections, why are we mixing template stuff into our logic?
This directive can be rewritten (even for very complicated cases!) much more simply like so:
.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;
};
}
};
});
Again, the template stuff is in the template, so you (or your users) can easily swap it out for one that meets any style necessary, and the logic never had to be touched. Reusability - boom!
And there are still all those other benefits, like testing - it's easy! No matter what's in the template, the directive's internal API is never touched, so refactoring is easy. You can change the template as much as you want without touching the directive. And no matter what you change, your tests still pass.
w00t!
So if directives aren't just collections of jQuery-like functions, what are they? Directives are actually extensions of HTML. If HTML doesn't do something you need it to do, you write a directive to do it for you, and then use it just as if it was part of HTML.
Put another way, if AngularJS doesn't do something out of the box, think how the team would accomplish it to fit right in with ngClick, ngClass, et al.
Summary
Don't even use jQuery. Don't even include it. It will hold you back. And when you come to a problem that you think you know how to solve in jQuery already, before you reach for the $, try to think about how to do it within the confines the AngularJS. If you don't know, ask! 19 times out of 20, the best way to do it doesn't need jQuery and to try to solve it with jQuery results in more work for you.
链接:http://stackoverflow.com/questions/14994391/thinking-in-angularjs-if-i-have-a-jquery-background
AngularJS学习路径:
我将一些资料筛选整理为三个阶段:
阶段一(Tutorial & Specification):
一个老外的学习blog-->>Nicholas Johnson
另一个老外的tutorial-->>Jakob Jenkov
阶段二(API Reference & Showcase):
Book: AngularJS 权威指南
基于bootstrap的范例集:Angular showcase
阶段三(Source Code):
Book: build your own angular 自己动手实现Angular
以上大部分为 Angular_1.X 的资料,推荐选择自己适合的教程去实践。
同时你也可以尝试从Angular 2(官方中文社区)开始。
具备 jQuery 经验的人如何学习AngularJS(附:学习路径)的更多相关文章
- 2019最新WEB前端开发小白必看的学习路线(附学习视频教程)
2019最新WEB前端开发小白必看的学习路线(附学习视频教程).web前端自学之路:史上最全web学习路线,HTML5是万维网的核心语言,标准通用标记语言下的一个应用超文本标记语言(HTML)的第五次 ...
- AngularJS 整理学习
参考博客: https://blog.csdn.net/weixin_33178524/article/details/79179597 https://blog.csdn.net/qq_42128 ...
- 【js类库AngularJs】学习angularJs的指令(包括常见表单验证,隐藏等功能)
[js类库AngularJs]学习angularJs的指令(包括常见表单验证,隐藏等功能) AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀 ...
- AngularJS系统学习之Scope(作用域)
本文出自:https://www.w3ctech.com/topic/1611 看完了没怎么懂, 也许是和别人 原文作者: Nicolas Bhttps://www.w3ctech.com/topi ...
- 十个非常棒的学习angularjs的英文网站
AngularJS 是非常棒的JS框架,能够创建功能强大,动态功能的Web app.AngularJS自2009发布以来,已经广泛应用于Web 开发中.但是对想要学习Angular JS 的人而言,只 ...
- Angularjs入门学习一 简介
本系列文章是从头开始学习angularjs,下文中用ng表示angularjs,要知道从以为根深蒂固的jquery开发者转变开发思想,确实需要一段时间,下面介绍以下 angularjs,我也是参考网上 ...
- 学习AngularJs:Directive指令用法(完整版)
这篇文章主要学习AngularJs:Directive指令用法,内容很全面,感兴趣的小伙伴们可以参考一下 本教程使用AngularJs版本:1.5.3 AngularJs GitHub: http ...
- 深入学习AngularJS中数据的双向绑定机制
来自:http://www.jb51.net/article/80454.htm Angular JS (Angular.JS) 是一组用来开发Web页面的框架.模板以及数据绑定和丰富UI组件.它支持 ...
- AngularJS进阶学习
参考:http://***/class/54f3ba65e564e50cfccbad4b 1. AJAX:Asynchronous JavaScript and XML(异步的 JavaScript ...
随机推荐
- Oracle之PL/SQL学习笔记
自己在学习Oracle是做的笔记及实验代码记录,内容挺全的,也挺详细,发篇博文分享给需要的朋友,共有1w多字的学习笔记吧.是以前做的,一直在压箱底,今天拿出来整理了一下,给大家分享,有不足之处还望大家 ...
- EntityFramework 7 Left Join Where Select 奇怪问题
这篇博文纪录一下:使用 EF7,当 Linq 查询中使用 "Left Join" 语法(DefaultIfEmpty),Where Select 不同条件语法实现,出现的不同问题. ...
- ZOJ Problem Set - 1331 Perfect Cubes 判断一个double是否为整数
zju对时间要求比较高,这就要求我们不能简单地暴力求解(三个循环搞定),就要换个思路:因为在循环时,已知a,确定b,c,d,在外重两层循环中已经给定了b和c,我们就不用遍历d,我们可以利用d^3=a^ ...
- 一台电脑上的git同时使用两个github账户
需求: 公司有github账号,自己有github账号,想在git上同时使用,两者互不干扰. 思路: 管理两个SHH key. 解决方案: 一.生成两个SSH key 为了举例方便,这里使用“one” ...
- “WPF老矣,尚能饭否”—且说说WPF今生未来(上):担心
近日微软公布了最新的WPF路线图,一片热议:对于老牌控件提供商葡萄城来说,这是WPF系列控件一个重要的机遇,因此,Spread Studio for WPF产品做了一次重要更新,并随着Spread S ...
- CSS垂直居中和水平居中
前言 CSS居中一直是一个比较敏感的话题,为了以后开发的方便,楼主觉得确实需要总结一下了,总的来说,居中问题分为垂直居中和水平居中,实际上水平居中是很简单的,但垂直居中的方式和方法就千奇百怪了. 内联 ...
- jQuery网页版五子棋小游戏源码下载
体验效果:http://hovertree.com/texiao/game/4/ 网页五子棋源代码: <!DOCTYPE html> <html> <head> & ...
- 利用SHELL脚本实现文件完整性检测程序(1.2版更新)
一..开发背景 因时势所逼,需要对服务器的文件系统实行监控.虽然linux下有不少入侵检测和防窜改系统,但都比较麻烦,用起来也不是很称手.自己琢磨着也不需要什么多复杂的功能,写个脚本应该就可以满足基本 ...
- iOS阶段学习第34天笔记(UI小组件 UISegment-UISlider-UIStepper-UIProgressView-UITextView介绍)
iOS学习(UI)知识点整理 一.UI小组件 1.UISegmentedControl 分段选择器 实例代码 - (void)viewDidLoad { [super viewDidLoad]; / ...
- java数据类型
对String来说,”==“是用来判断两个字符串(对象)的地址是否相同,即判断是否是同一个字符串的应用.”equals()“则是判断两个字符串(对象)的值是否相等,如果相等则返回true.一般情况下, ...