Javascript 如果我有 jQuery 背景,“在 AngularJS 中思考”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14994391/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Thinking in AngularJS" if I have a jQuery background?
提问by Mark Rajcok
Suppose I'm familiar with developing client-side applications in jQuery, but now I'd like to start using AngularJS. Can you describe the paradigm shift that is necessary? Here are a few questions that might help you frame an answer:
假设我熟悉用jQuery开发客户端应用程序,但现在我想开始使用AngularJS。你能描述一下必要的范式转变吗?以下是一些可能有助于您确定答案的问题:
- How do I architect and design client-side web applications differently? What is the biggest difference?
- What should I stop doing/using; What should I start doing/using instead?
- Are there any server-side considerations/restrictions?
- 我如何以不同的方式构建和设计客户端 Web 应用程序?最大的区别是什么?
- 我应该停止做什么/使用什么;我应该开始做什么/使用什么?
- 是否有任何服务器端注意事项/限制?
I'm not looking for a detailed comparison between jQueryand AngularJS.
我不是在寻找jQuery和之间的详细比较AngularJS。
回答by Josh David Miller
1. Don't design your page, and then change it with DOMmanipulations
1.不要设计你的页面,然后用DOM操作改变它
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.
在 jQuery 中,您设计一个页面,然后使其动态化。这是因为 jQuery 是为增强而设计的,并且在这个简单的前提下已经取得了令人难以置信的发展。
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.
但是在 AngularJS 中,您必须从头开始考虑您的架构。与其从思考“我有这块 DOM 并且我想让它做 X”开始,你必须从你想要完成的事情开始,然后设计你的应用程序,最后设计你的视图。
2. Don't augment jQuery with AngularJS
2. 不要用 AngularJS 来扩充 jQuery
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 reallytempting 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".
同样,不要以为 jQuery 可以执行 X、Y 和 Z 的想法开始,所以我将在模型和控制器的基础上添加 AngularJS。这是真的,当你刚刚起步的,这就是为什么我总是建议新AngularJS开发完全不使用jQuery,至少直到他们习惯做的事情“角路”诱人。
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 mostcases that jQuery plugin could be rewritten in AngularJS in a fraction of the code, where suddenly everything becomes comprehensible and straightforward.
我在这里和邮件列表上看到许多开发人员使用 150 或 200 行代码的 jQuery 插件创建了这些精心设计的解决方案,然后他们将这些复杂的回调和$applys的集合粘合到 AngularJS 中,这些令人困惑和费解;但他们最终让它发挥作用!问题是在大多数情况下,jQuery 插件可以用 AngularJS 重写一小部分代码,突然之间一切都变得易于理解和直接了当。
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, thenfeel free to reach for the jQuery. But don't let jQuery become a crutch or you'll never master AngularJS.
底线是这样的:在解决时,首先“在 AngularJS 中思考”;如果您想不出解决方案,请询问社区;如果毕竟没有简单的解决方案,那么请随时使用 jQuery。但是不要让 jQuery 成为拐杖,否则您将永远无法掌握 AngularJS。
3. Always think in terms of architecture
3. 始终从架构的角度思考
First know that single-page applicationsare applications. They're notwebpages. So we need to think like a server-side developer in additionto thinking like a client-side developer. We have to think about how to divide our application into individual, extensible, testable components.
首先要知道单页应用程序是应用程序。它们不是网页。因此,除了像客户端开发人员一样思考之外,我们还需要像服务器端开发人员一样思考。我们必须考虑如何将我们的应用程序划分为单独的、可扩展的、可测试的组件。
So then howdo you do that? How do you "think in AngularJS"? Here are some general principles, contrasted with jQuery.
那么接下来怎么做呢?你如何“在 AngularJS 中思考”?下面是一些与 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:
在 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>
In jQuery, in our application logic, we would activate it with something like:
在 jQuery 中,在我们的应用程序逻辑中,我们将使用以下内容激活它:
$('.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 uldeclaration would look like this instead:
然而,在 AngularJS 中,视图是基于视图的功能的官方记录。我们的ul声明看起来像这样:
<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 knowthat there is a directive called dropdownMenuoperating 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.
这两个做同样的事情,但在 AngularJS 版本中,任何查看模板的人都知道应该发生什么。每当开发团队的新成员加入时,她可以查看此内容,然后知道有一个名为dropdownMenu操作的指令;她不需要凭直觉得出正确答案或筛选任何代码。视图告诉我们应该发生什么。干净多了。
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 isthe 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.
刚接触 AngularJS 的开发人员经常会问这样的问题:如何找到特定类型的所有链接并在其中添加指令。当我们回答:你没有时,开发人员总是大吃一惊。但你不这样做的原因是这就像半 jQuery、半 AngularJS,而且不好。这里的问题是开发人员试图在 AngularJS 的上下文中“执行 jQuery”。这永远不会奏效。该视图是官方记录。在指令之外(更多内容见下文),您永远永远永远不会更改 DOM。并且指令被应用在视图中,所以意图很明确。
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:
这是迄今为止 AngularJS 最棒的功能之一,并且省去了我在上一节中提到的各种 DOM 操作的需要。AngularJS 会自动更新你的视图,所以你不必更新!在 jQuery 中,我们响应事件然后更新内容。就像是:
$.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?
除了混合关注点之外,我们也有我之前提到的表示意图的相同问题。但更重要的是,我们必须手动引用和更新 DOM 节点。如果我们想删除一个日志条目,我们也必须针对 DOM 进行编码。除了DOM,我们如何测试逻辑?如果我们想更改演示文稿怎么办?
This a little messy and a trifle frail. But in AngularJS, we can do this:
这有点凌乱,有点脆弱。但是在 AngularJS 中,我们可以这样做:
$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 whereor howthe log gets updated, the view will change too. Automatically. Neat!
现在我们不再使用无序列表,而是使用 Bootstrap 警告框。而且我们永远不必更改控制器代码!但更重要的是,无论日志在何处或如何更新,视图也会发生变化。自动地。整洁的!
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.
虽然我没有在这里展示它,但数据绑定是双向的。因此,这些日志信息,也可以在视图编辑只是这样做:<input ng-model="entry.msg" />。有很多的欣喜。
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.
在 jQuery 中,DOM 有点像模型。但是在 AngularJS 中,我们有一个单独的模型层,我们可以以任何我们想要的方式管理它,完全独立于视图。这有助于上述数据绑定,维护关注点分离,并引入了更大的可测试性。其他答案提到了这一点,所以我就留在那里。
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.
以上所有内容都与这个总体主题有关:将您的顾虑分开。你的观点是应该发生的事情的官方记录(大部分);您的模型代表您的数据;你有一个服务层来执行可重用的任务;您进行 DOM 操作并使用指令扩充您的视图;然后你用控制器把它们粘在一起。其他答案中也提到了这一点,我唯一要添加的内容与可测试性有关,我将在下面的另一部分中讨论。
Dependency injection
依赖注入
To help us out with separation of concerns is dependency injection(DI). If you come from a server-side language (from Javato 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. :-)
帮助我们解决关注点分离的是依赖注入(DI)。如果您来自服务器端语言(从Java到PHP),您可能已经熟悉这个概念,但如果您是来自 jQuery 的客户端,这个概念可能看起来从愚蠢到多余再到时髦. 但事实并非如此。:-)
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.
从广泛的角度来看,DI 意味着您可以非常自由地声明组件,然后从任何其他组件中,只需请求它的一个实例,它就会被授予。您不必知道加载顺序、文件位置或类似内容。威力可能不会立即显现,但我将仅提供一个(常见)示例:测试。
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.
假设在我们的应用程序中,我们需要一个通过RESTAPI实现服务器端存储的服务,并且根据应用程序状态,本地存储也是如此。在我们的控制器上运行测试时,我们不想与服务器通信 -毕竟我们正在测试控制器。我们可以添加一个与原始组件同名的模拟服务,注入器将确保我们的控制器自动获取假的服务——我们的控制器不知道也不需要知道区别。
Speaking of testing...
说到测试...
4. Test-driven development - always
4. 测试驱动的开发——永远
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.
这实际上是关于架构的第 3 部分的一部分,但它非常重要,我将其作为自己的顶级部分。
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.
在您见过、使用或编写过的所有 jQuery 插件中,有多少带有随附的测试套件?不是很多,因为 jQuery 不太适合。但 AngularJS 是。
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 thenintegrate 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?
在 jQuery 中,测试的唯一方法通常是使用示例/演示页面独立创建组件,我们的测试可以针对该页面执行 DOM 操作。那么我们必须单独开发一个组件,然后将其集成到我们的应用程序中。多么不方便!很多时候,当使用 jQuery 进行开发时,我们选择迭代而不是测试驱动的开发。谁能怪我们?
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:
但是因为我们有关注点分离,所以我们可以在 AngularJS 中迭代地进行测试驱动开发!例如,假设我们想要一个超级简单的指令在我们的菜单中指示我们当前的路线是什么。我们可以在应用程序的视图中声明我们想要的内容:
<a href="/hello" when-active>Hello</a>
Okay, now we can write a test for the non-existent when-activedirective:
好的,现在我们可以为不存在的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();
}));
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 andour menu performs as requested. Our development is bothiterative andtest-driven. Wicked-cool.
我们的测试现在通过了,我们的菜单按要求执行。我们的开发既是迭代的,也是测试驱动的。酷酷的。
5. Conceptually, directives are notpackaged jQuery
5. 从概念上讲,指令不是jQuery 封装的
You'll often hear "only do DOM manipulation in a directive". This is a necessity.Treat it with due deference!
您经常会听到“只在指令中进行 DOM 操作”。这是必需品。以应有的尊重对待它!
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 alsorespect separation of concerns. That is, the template tooshould remain largely independent from its implementation in the link and controller functions.
一些指令只是装饰视图中已经存在的内容(想想ngClass),因此有时会立即进行 DOM 操作,然后基本上就完成了。但是如果一个指令就像一个“小部件”并且有一个模板,它也应该尊重关注点分离。也就是说,模板也应该在很大程度上独立于它在链接和控制器功能中的实现。
AngularJS comes with an entire set of tools to make this very easy; with ngClasswe can dynamically update the class; ngModelallows two-way data binding; ngShowand 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 withoutDOM 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.
AngularJS 附带了一整套工具,使这变得非常容易;与ngClass我们可以动态更新的类; ngModel允许双向数据绑定;ngShow并以ngHide编程方式显示或隐藏元素;还有更多——包括我们自己编写的那些。换句话说,我们可以在没有DOM 操作的情况下做各种令人敬畏的事情。DOM 操作越少,指令越容易测试,它们越容易设计样式,它们在未来越容易改变,它们的可重用性和可分发性越强。
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.
我看到许多刚接触 AngularJS 的开发人员使用指令作为抛出一堆 jQuery 的地方。换句话说,他们认为“由于我无法在控制器中进行 DOM 操作,我会将这些代码放入指令中”。虽然这当然要好得多,但它通常仍然是错误的。
Think of the logger we programmed in section 3. Even if we put that in a directive, we stillwant to do it the "Angular Way". It stilldoesn't take any DOM manipulation! There are lots of times when DOM manipulation is necessary, but it's a lotrarer than you think! Before doing DOM manipulation anywherein your application, ask yourself if you really need to. There might be a better way.
想想我们在第 3 节中编写的记录器。即使我们将它放在指令中,我们仍然希望以“Angular 方式”来实现。它仍然不需要任何 DOM 操作!很多时候都需要 DOM 操作,但它比您想象的要少得多!在应用程序的任何地方进行 DOM 操作之前,先问问自己是否真的需要这样做。可能有更好的方法。
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 wasrequired for this directive to work, jqLite (
angular.element) will alwaysuse 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 bea jQuery element! - And fifth, which we've mentioned in previous sections, why are we mixing template stuff into our logic?
- 首先,jQuery 从来都不是必需的。我们在这里做的任何事情都不需要 jQuery!
- 其次,即使我们的页面上已经有 jQuery,也没有理由在这里使用它;我们可以简单地使用
angular.element,当放入一个没有 jQuery 的项目时,我们的组件仍然可以工作。 - 第三,即使假设jQuery的是需要这种指令工作,jqLite(
angular.element)将始终使用jQuery,如果它是装的!所以我们不需要使用$- 我们可以使用angular.element. - 第四,与第三个密切相关的是 jqLite 元素不需要被包裹
$——element传递给link函数的元素已经是一个 jQuery 元素! - 第五,我们在前面的部分提到过,为什么我们将模板内容混合到我们的逻辑中?
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 logicnever 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.
而且还有所有其他好处,例如测试 - 这很容易!无论模板中有什么,指令的内部 API 都不会被触及,因此重构很容易。您可以根据需要随意更改模板,而无需更改指令。无论您更改什么,您的测试仍然通过。
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.
因此,如果指令不仅仅是类似 jQuery 的函数的集合,那么它们是什么?指令实际上是 HTML 的扩展。如果 HTML 没有做你需要它做的事情,你可以编写一个指令来为你做,然后就像它是 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.
换句话说,如果 AngularJS 不做一些开箱即用的事情,请考虑团队将如何完成它以适应ngClick, ngClass, 等。
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.
甚至不要使用jQuery。甚至不要包括它。它会阻止你。当你遇到一个你认为你已经知道如何在 jQuery 中解决的问题时,在你使用$. 不知道就问!20 次中有 19 次,最好的方法是不需要 jQuery,而尝试用 jQuery 解决它会为您带来更多的工作。
回答by Mark Rajcok
Imperative → declarative
命令式 → 声明式
In jQuery, selectorsare used to find DOMelements and then bind/register event handlers to them. When an event triggers, that (imperative) code executes to update/change the DOM.
在 jQuery 中,选择器用于查找DOM元素,然后为它们绑定/注册事件处理程序。当事件触发时,该(命令式)代码会执行以更新/更改 DOM。
In AngularJS, you want to think about viewsrather than DOM elements. Views are (declarative) HTML that contain AngularJS directives. Directives set up the event handlers behind the scenes for us and give us dynamic databinding. Selectors are rarely used, so the need for IDs (and some types of classes) is greatly diminished. Views are tied to models(via scopes). Views are a projection of the model. Events change models (that is, data, scope properties), and the views that project those models update "automatically."
在 AngularJS 中,您需要考虑视图而不是 DOM 元素。视图是包含 AngularJS指令的(声明性)HTML 。指令在幕后为我们设置事件处理程序,并为我们提供动态数据绑定。选择器很少使用,因此对 ID(和某些类型的类)的需求大大减少。视图与模型相关联(通过作用域)。视图是模型的投影。事件更改模型(即数据、范围属性),并且投影这些模型的视图“自动”更新。
In AngularJS, think about models, rather than jQuery-selected DOM elements that hold your data. Think about views as projections of those models, rather than registering callbacks to manipulate what the user sees.
在 AngularJS 中,考虑模型,而不是 jQuery 选择的保存数据的 DOM 元素。将视图视为这些模型的投影,而不是注册回调来操纵用户看到的内容。
Separation of concerns
关注点分离
jQuery employs unobtrusive JavaScript- behavior (JavaScript) is separated from the structure (HTML).
jQuery 采用不显眼的 JavaScript- 行为 (JavaScript) 与结构 (HTML) 分离。
AngularJS uses controllersand directives (each of which can have their own controller, and/or compile and linking functions) to remove behavior from the view/structure (HTML). Angular also has servicesand filtersto help separate/organize your application.
AngularJS 使用控制器和指令(每个都可以有自己的控制器,和/或编译和链接函数)从视图/结构(HTML)中删除行为。Angular 也有服务和过滤器来帮助分离/组织你的应用程序。
See also https://stackoverflow.com/a/14346528/215945
另见https://stackoverflow.com/a/14346528/215945
Application design
应用设计
One approach to designing an AngularJS application:
设计 AngularJS 应用程序的一种方法:
- Think about your models. Create services or your own JavaScript objects for those models.
- Think about how you want to present your models -- your views. Create HTML templates for each view, using the necessary directives to get dynamic databinding.
- Attach a controller to each view (using ng-view and routing, or ng-controller). Have the controller find/get only whatever model data the view needs to do its job. Make controllers as thin as possible.
- 想想你的模型。为这些模型创建服务或您自己的 JavaScript 对象。
- 想想你想如何展示你的模型——你的观点。为每个视图创建 HTML 模板,使用必要的指令来获取动态数据绑定。
- 将控制器附加到每个视图(使用 ng-view 和路由,或 ng-controller)。让控制器仅查找/获取视图完成其工作所需的任何模型数据。使控制器尽可能薄。
Prototypal inheritance
原型继承
You can do a lot with jQuery without knowing about how JavaScript prototypal inheritance works. When developing AngularJS applications, you will avoid some common pitfalls if you have a good understanding of JavaScript inheritance. Recommended reading: What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
您可以使用 jQuery 做很多事情,而无需了解 JavaScript 原型继承的工作原理。在开发 AngularJS 应用程序时,如果您对 JavaScript 继承有很好的理解,您将避免一些常见的陷阱。推荐阅读:AngularJS 中范围原型/原型继承的细微差别是什么?
回答by superluminary
AngularJS vs. jQuery
AngularJS 与 jQuery
AngularJS and jQuery adopt very different ideologies. If you're coming from jQuery you may find some of the differences surprising. Angular may make you angry.
AngularJS 和 jQuery 采用非常不同的意识形态。如果您来自 jQuery,您可能会发现一些令人惊讶的差异。Angular 可能会让你生气。
This is normal, you should push through. Angular is worth it.
这是正常的,你应该挺过去。角是值得的。
The big difference (TLDR)
大不同(TLDR)
jQuery gives you a toolkit for selecting arbitrary bits of the DOM and making ad-hoc changes to them. You can do pretty much anything you like piece by piece.
jQuery 为您提供了一个工具包,用于选择 DOM 的任意位并对它们进行临时更改。你几乎可以一点一点地做任何你喜欢的事情。
AngularJS instead gives you a compiler.
相反,AngularJS 为您提供了一个编译器。
What this means is that AngularJS reads your entire DOM from top to bottom and treats it as code, literally as instructions to the compiler. As it traverses the DOM, It looks for specific directives(compiler directives) that tell the AngularJS compiler how to behave and what to do. Directives are little objects full of JavaScript which can match against attributes, tags, classes or even comments.
这意味着 AngularJS 从上到下读取你的整个 DOM 并将其视为代码,字面意思是编译器的指令。当它遍历 DOM 时,它会寻找告诉 AngularJS 编译器如何表现和做什么的特定指令(编译器指令)。指令是充满 JavaScript 的小对象,可以匹配属性、标签、类甚至注释。
When the Angular compiler determines that a piece of the DOM matches a particular directive, it calls the directive function, passing it the DOM element, any attributes, the current $scope (which is a local variable store), and some other useful bits. These attributes may contain expressions which can be interpreted by the Directive, and which tell it how to render, and when it should redraw itself.
当 Angular 编译器确定 DOM 的一部分与特定指令匹配时,它会调用指令函数,将 DOM 元素、任何属性、当前 $scope(这是一个局部变量存储)和一些其他有用的位传递给它。这些属性可能包含可由指令解释的表达式,并告诉它如何呈现,以及何时应重绘自身。
Directives can then in turn pull in additional Angular components such as controllers, services, etc. What comes out the bottom of the compiler is a fully formed web application, wired up and ready to go.
然后,指令可以反过来引入额外的 Angular 组件,例如控制器、服务等。编译器底部出来的是一个完整的 Web 应用程序,连接好并准备就绪。
This means that Angular is Template Driven. Your template drives the JavaScript, not the other way around. This is a radical reversal of roles, and the complete opposite of the unobtrusive JavaScript we have been writing for the last 10 years or so. This can take some getting used to.
这意味着 Angular 是模板驱动的。您的模板驱动 JavaScript,而不是相反。这是一个彻底的角色转换,与我们过去 10 年左右一直在编写的不引人注目的 JavaScript 完全相反。这可能需要一些时间来适应。
If this sounds like it might be over-prescriptive and limiting, nothing could be farther from the truth. Because AngularJS treats your HTML as code, you get HTML level granularity in your web application. Everything is possible, and most things are surprisingly easy once you make a few conceptual leaps.
如果这听起来可能过于规范和限制,那么事实并非如此。由于 AngularJS 将您的 HTML 视为代码,因此您可以在 Web 应用程序中获得HTML 级别的粒度。一切皆有可能,一旦您在概念上进行了一些飞跃,大多数事情都会出奇地简单。
Let's get down to the nitty gritty.
让我们深入了解细节。
First up, Angular doesn't replace jQuery
首先,Angular 不会取代 jQuery
Angular and jQuery do different things. AngularJS gives you a set of tools to produce web applications. jQuery mainly gives you tools for modifying the DOM. If jQuery is present on your page, AngularJS will use it automatically. If it isn't, AngularJS ships with jQuery Lite, which is a cut down, but still perfectly usable version of jQuery.
Angular 和 jQuery 做不同的事情。AngularJS 为您提供了一组用于生成 Web 应用程序的工具。jQuery 主要为您提供修改 DOM 的工具。如果您的页面上存在 jQuery,AngularJS 将自动使用它。如果不是,AngularJS 附带了 jQuery Lite,它是 jQuery 的精简版,但仍然是完美可用的 jQuery 版本。
Misko likes jQuery and doesn't object to you using it. However you will find as you advance that you can get a pretty much all of your work done using a combination of scope, templates and directives, and you should prefer this workflow where possible because your code will be more discrete, more configurable, and more Angular.
Misko 喜欢 jQuery 并且不反对你使用它。但是,您会发现,随着工作的进展,您可以使用范围、模板和指令的组合来完成几乎所有的工作,并且您应该尽可能选择这种工作流程,因为您的代码将更加离散、更加可配置等等棱角分明。
If you do use jQuery, you shouldn't be sprinkling it all over the place. The correct place for DOM manipulation in AngularJS is in a directive. More on these later.
如果您确实使用了 jQuery,则不应将其洒在所有地方。AngularJS 中 DOM 操作的正确位置是在指令中。稍后会详细介绍这些。
Unobtrusive JavaScript with Selectors vs. Declarative Templates
带有选择器的不显眼的 JavaScript 与声明性模板
jQuery is typically applied unobtrusively. Your JavaScript code is linked in the header (or the footer), and this is the only place it is mentioned. We use selectors to pick out bits of the page and write plugins to modify those parts.
jQuery 通常以不显眼的方式应用。您的 JavaScript 代码链接在页眉(或页脚)中,这是唯一提到的地方。我们使用选择器来挑选页面的部分并编写插件来修改这些部分。
The JavaScript is in control. The HTML has a completely independent existence. Your HTML remains semantic even without JavaScript. Onclick attributes are very bad practice.
JavaScript 处于控制之中。HTML具有完全独立的存在。即使没有 JavaScript,您的 HTML 也保持语义。Onclick 属性是非常糟糕的做法。
One of the first things your will notice about AngularJS is that custom attributes are everywhere. Your HTML will be littered with ng attributes, which are essentially onClick attributes on steroids. These are directives (compiler directives), and are one of the main ways in which the template is hooked to the model.
关于 AngularJS,您会注意到的第一件事是自定义属性无处不在。您的 HTML 将充斥着 ng 属性,这些属性本质上是类固醇上的 onClick 属性。这些是指令(编译器指令),是模板与模型挂钩的主要方式之一。
When you first see this you might be tempted to write AngularJS off as old school intrusive JavaScript (like I did at first). In fact, AngularJS does not play by those rules. In AngularJS, your HTML5 is a template. It is compiled by AngularJS to produce your web page.
当你第一次看到这个时,你可能会想把 AngularJS 写成老式的侵入式 JavaScript(就像我一开始做的那样)。事实上,AngularJS 并不遵守这些规则。在 AngularJS 中,你的 HTML5 是一个模板。它由 AngularJS 编译以生成您的网页。
This is the first big difference. To jQuery, your web page is a DOM to be manipulated. To AngularJS, your HTML is code to be compiled. AngularJS reads in your whole web page and literally compiles it into a new web page using its built in compiler.
这是第一个很大的不同。对 jQuery 来说,你的网页就是一个被操纵的 DOM。对于 AngularJS,您的 HTML 是要编译的代码。AngularJS 会读入你的整个网页,并使用其内置的编译器将其编译成一个新的网页。
Your template should be declarative; its meaning should be clear simply by reading it. We use custom attributes with meaningful names. We make up new HTML elements, again with meaningful names. A designer with minimal HTML knowledge and no coding skill can read your AngularJS template and understand what it is doing. He or she can make modifications. This is the Angular way.
你的模板应该是声明性的;只需阅读它,它的含义就应该很清楚。我们使用具有有意义名称的自定义属性。我们用有意义的名字来组成新的 HTML 元素。具有最少 HTML 知识且没有编码技能的设计师可以阅读您的 AngularJS 模板并了解它在做什么。他或她可以进行修改。这是 Angular 的方式。
The template is in the driving seat.
模板在驾驶座上。
One of the first questions I asked myself when starting AngularJS and running through the tutorials is "Where is my code?". I've written no JavaScript, and yet I have all this behaviour. The answer is obvious. Because AngularJS compiles the DOM, AngularJS is treating your HTML as code. For many simple cases it's often sufficient to just write a template and let AngularJS compile it into an application for you.
在启动 AngularJS 和浏览教程时,我问自己的第一个问题是“我的代码在哪里?” . 我没有编写 JavaScript,但我有所有这些行为。答案是显而易见的。因为 AngularJS 编译 DOM,AngularJS 将您的 HTML 视为代码。对于许多简单的情况,通常只编写一个模板并让 AngularJS 为您编译成一个应用程序就足够了。
Your template drives your application. It's treated as a DSL. You write AngularJS components, and AngularJS will take care of pulling them in and making them available at the right time based on the structure of your template. This is very different to a standard MVCpattern, where the template is just for output.
您的模板驱动您的应用程序。它被视为DSL。您编写 AngularJS 组件,AngularJS 将负责将它们拉入并根据模板的结构在正确的时间使它们可用。这与标准MVC模式非常不同,其中模板仅用于输出。
It's more similar to XSLTthan Ruby on Railsfor example.
例如,它比Ruby on Rails更类似于XSLT。
This is a radical inversion of control that takes some getting used to.
这是一种彻底的控制反转,需要一些时间来适应。
Stop trying to drive your application from your JavaScript. Let the template drive the application, and let AngularJS take care of wiring the components together. This also is the Angular way.
停止尝试通过 JavaScript 驱动您的应用程序。让模板驱动应用程序,让 AngularJS 负责将组件连接在一起。这也是 Angular 的方式。
Semantic HTML vs. Semantic Models
语义 HTML 与语义模型
With jQuery your HTML page should contain semantic meaningful content. If the JavaScript is turned off (by a user or search engine) your content remains accessible.
使用 jQuery,您的 HTML 页面应该包含语义上有意义的内容。如果 JavaScript 被关闭(由用户或搜索引擎),您的内容仍然可以访问。
Because AngularJS treats your HTML page as a template. The template is not supposed to be semantic as your content is typically stored in your model which ultimately comes from your API. AngularJS compiles your DOM with the model to produce a semantic web page.
因为 AngularJS 将您的 HTML 页面视为模板。该模板不应该是语义的,因为您的内容通常存储在最终来自您的 API 的模型中。AngularJS 使用模型编译您的 DOM 以生成语义网页。
Your HTML source is no longer semantic, instead, your API and compiled DOM are semantic.
你的 HTML 源代码不再是语义的,相反,你的 API 和编译的 DOM 是语义的。
In AngularJS, meaning lives in the model, the HTML is just a template, for display only.
在 AngularJS 中,意味着存在于模型中,HTML 只是一个模板,仅用于显示。
At this point you likely have all sorts of questions concerning SEOand accessibility, and rightly so. There are open issues here. Most screen readers will now parse JavaScript. Search engines can also index AJAXedcontent. Nevertheless, you will want to make sure you are using pushstate URLs and you have a decent sitemap. See here for a discussion of the issue: https://stackoverflow.com/a/23245379/687677
在这一点上,您可能对SEO和可访问性有各种疑问,这是正确的。这里有未解决的问题。大多数屏幕阅读器现在都会解析 JavaScript。搜索引擎还可以索引AJAX内容。尽管如此,您还是要确保您使用的是 pushstate URL,并且您有一个不错的站点地图。有关该问题的讨论,请参见此处:https: //stackoverflow.com/a/23245379/687677
Separation of concerns (SOC) vs. MVC
关注点分离 (SOC) 与 MVC
Separation of concerns(SOC) is a pattern that grew up over many years of web development for a variety of reasons including SEO, accessibility and browser incompatibility. It looks like this:
关注点分离(SOC) 是一种在多年 Web 开发中成长起来的模式,其原因有多种,包括 SEO、可访问性和浏览器不兼容。它看起来像这样:
- HTML - Semantic meaning. The HTML should stand alone.
- CSS - Styling, without the CSS the page is still readable.
- JavaScript - Behaviour, without the script the content remains.
- HTML - 语义。HTML 应该是独立的。
- CSS - 样式,没有 CSS 页面仍然可读。
- JavaScript - 行为,没有脚本内容仍然存在。
Again, AngularJS does not play by their rules. In a stroke, AngularJS does away with a decade of received wisdomand instead implements an MVC pattern in which the template is no longer semantic, not even a little bit.
同样,AngularJS 不遵守他们的规则。一下子,AngularJS 摒弃了十年公认的智慧,而是实现了一种 MVC 模式,其中模板不再具有语义,甚至没有一点。
It looks like this:
它看起来像这样:
- Model - your models contains your semantic data. Models are usually JSONobjects. Models exist as attributes of an object called $scope. You can also store handy utility functions on $scope which your templates can then access.
- View - Your views are written in HTML. The view is usually not semantic because your data lives in the model.
- Controller - Your controller is a JavaScript function which hooks the view to the model. Its function is to initialise $scope. Depending on your application, you may or may not need to create a controller. You can have many controllers on a page.
- 模型 - 您的模型包含您的语义数据。模型通常是JSON对象。模型作为名为 $scope 的对象的属性存在。您还可以在 $scope 上存储方便的实用程序函数,然后您的模板可以访问这些函数。
- 视图 - 您的视图是用 HTML 编写的。视图通常不是语义的,因为您的数据存在于模型中。
- 控制器 - 您的控制器是一个 JavaScript 函数,它将视图与模型挂钩。它的作用是初始化$scope。根据您的应用程序,您可能需要也可能不需要创建控制器。一个页面上可以有多个控制器。
MVC and SOC are not on opposite ends of the same scale, they are on completely different axes. SOC makes no sense in an AngularJS context. You have to forget it and move on.
MVC 和 SOC 不在同一尺度的两端,它们在完全不同的轴上。SOC 在 AngularJS 上下文中毫无意义。你必须忘记它并继续前进。
If, like me, you lived through the browser wars, you might find this idea quite offensive. Get over it, it'll be worth it, I promise.
如果你像我一样经历过浏览器大战,你可能会觉得这个想法很冒犯。克服它,这将是值得的,我保证。
Plugins vs. Directives
插件与指令
Plugins extend jQuery. AngularJS Directives extend the capabilities of your browser.
插件扩展了 jQuery。AngularJS 指令扩展了浏览器的功能。
In jQuery we define plugins by adding functions to the jQuery.prototype. We then hook these into the DOM by selecting elements and calling the plugin on the result. The idea is to extend the capabilities of jQuery.
在 jQuery 中,我们通过向 jQuery.prototype 添加函数来定义插件。然后我们通过选择元素并在结果上调用插件来将它们挂接到 DOM 中。这个想法是扩展 jQuery 的功能。
For example, if you want a carousel on your page, you might define an unordered list of figures, perhaps wrapped in a nav element. You might then write some jQuery to select the list on the page and restyle it as a gallery with timeouts to do the sliding animation.
例如,如果您想在页面上使用轮播,您可以定义一个无序列表的数字,可能包含在一个 nav 元素中。然后,您可能会编写一些 jQuery 来选择页面上的列表,并将其重新设置为带有超时的画廊以执行滑动动画。
In AngularJS, we define directives. A directive is a function which returns a JSON object. This object tells AngularJS what DOM elements to look for, and what changes to make to them. Directives are hooked in to the template using either attributes or elements, which you invent. The idea is to extend the capabilities of HTML with new attributes and elements.
在 AngularJS 中,我们定义指令。指令是一个返回 JSON 对象的函数。这个对象告诉 AngularJS 要查找哪些 DOM 元素,以及要对它们进行哪些更改。指令使用您发明的属性或元素连接到模板。这个想法是用新的属性和元素扩展 HTML 的功能。
The AngularJS way is to extend the capabilities of native looking HTML.You should write HTML that looks like HTML, extended with custom attributes and elements.
AngularJS 的方式是扩展原生 HTML 的功能。您应该编写看起来像 HTML 的 HTML,并使用自定义属性和元素进行扩展。
If you want a carousel, just use a <carousel />element, then define a directive to pull in a template, and make that sucker work.
如果你想要一个旋转木马,只需使用一个<carousel />元素,然后定义一个指令来拉入一个模板,让这个傻瓜工作。
Lots of small directives vs. big plugins with configuration switches
许多带有配置开关的小指令与大插件
The tendency with jQuery is to write great big plugins like lightbox which we then configure by passing in numerous values and options.
jQuery 的趋势是编写像灯箱这样的大型插件,然后我们通过传入大量值和选项来配置这些插件。
This is a mistake in AngularJS.
这是 AngularJS 中的一个错误。
Take the example of a dropdown. When writing a dropdown plugin you might be tempted to code in click handlers, perhaps a function to add in a chevron which is either up or down, perhaps change the class of the unfolded element, show hide the menu, all helpful stuff.
以下拉列表为例。在编写下拉插件时,您可能会想在点击处理程序中编写代码,也许是添加一个向上或向下的人字形的函数,也许更改展开元素的类,显示隐藏菜单,所有有用的东西。
Until you want to make a small change.
直到你想做一个小的改变。
Say you have a menu that you want to unfold on hover. Well now we have a problem. Our plugin has wired in our click handler for us, we're going to need to add a configuration option to make it behave differently in this specific case.
假设您有一个要在悬停时展开的菜单。那么现在我们有一个问题。我们的插件已为我们连接到我们的点击处理程序中,我们将需要添加一个配置选项以使其在这种特定情况下的行为有所不同。
In AngularJS we write smaller directives. Our dropdown directive would be ridiculously small. It might maintain the folded state, and provide methods to fold(), unfold() or toggle(). These methods would simply update $scope.menu.visible which is a boolean holding the state.
在 AngularJS 中,我们编写更小的指令。我们的下拉指令会小得离谱。它可能保持折叠状态,并提供 fold()、unfold() 或 toggle() 方法。这些方法只会更新 $scope.menu.visible ,它是一个保持状态的布尔值。
Now in our templatewe can wire this up:
现在在我们的模板中,我们可以将其连接起来:
<a ng-click="toggle()">Menu</a>
<ul ng-show="menu.visible">
...
</ul>
Need to update on mouseover?
需要更新鼠标悬停?
<a ng-mouseenter="unfold()" ng-mouseleave="fold()">Menu</a>
<ul ng-show="menu.visible">
...
</ul>
The template drives the application so we get HTML level granularity. If we want to make case by case exceptions, the template makes this easy.
模板驱动应用程序,因此我们可以获得 HTML 级别的粒度。如果我们想逐个处理例外,模板使这变得容易。
Closure vs. $scope
关闭与 $scope
JQuery plugins are created in a closure. Privacy is maintained within that closure. It's up to you to maintain your scope chain within that closure. You only really have access to the set of DOM nodes passed in to the plugin by jQuery, plus any local variables defined in the closure and any globals you have defined. This means that plugins are quite self contained. This is a good thing, but can get restrictive when creating a whole application. Trying to pass data between sections of a dynamic page becomes a chore.
JQuery 插件是在一个闭包中创建的。在该关闭中保持隐私。由您来维护该闭包内的作用域链。您实际上只能访问 jQuery 传递给插件的 DOM 节点集,以及在闭包中定义的任何局部变量和您定义的任何全局变量。这意味着插件是完全独立的。这是一件好事,但在创建整个应用程序时可能会受到限制。尝试在动态页面的部分之间传递数据成为一件苦差事。
AngularJS has $scope objects. These are special objects created and maintained by AngularJS in which you store your model. Certain directives will spawn a new $scope, which by default inherits from its wrapping $scope using JavaScript prototypical inheritance. The $scope object is accessible in the controller and the view.
AngularJS 有 $scope 对象。这些是由 AngularJS 创建和维护的特殊对象,您可以在其中存储模型。某些指令会产生一个新的 $scope,默认情况下,它使用 JavaScript 原型继承从它的包装 $scope 继承。$scope 对象可在控制器和视图中访问。
This is the clever part. Because the structure of $scope inheritance roughly follows the structure of the DOM, elements have access to their own scope, and any containing scopes seamlessly, all the way up to the global $scope (which is not the same as the global scope).
这是聪明的部分。因为 $scope 继承的结构大致遵循 DOM 的结构,元素可以访问自己的作用域,并且可以无缝访问任何包含的作用域,一直到全局 $scope(与全局作用域不同)。
This makes it much easier to pass data around, and to store data at an appropriate level. If a dropdown is unfolded, only the dropdown $scope needs to know about it. If the user updates their preferences, you might want to update the global $scope, and any nested scopes listening to the user preferences would automatically be alerted.
这使得传递数据和在适当级别存储数据变得更加容易。如果下拉菜单被展开,则只有下拉菜单 $scope 需要知道它。如果用户更新了他们的首选项,您可能希望更新全局 $scope,并且任何监听用户首选项的嵌套范围都会自动收到警报。
This might sound complicated, in fact, once you relax into it, it's like flying. You don't need to create the $scope object, AngularJS instantiates and configures it for you, correctly and appropriately based on your template hierarchy. AngularJS then makes it available to your component using the magic of dependency injection (more on this later).
这听起来可能很复杂,事实上,一旦你放松下来,就像飞行一样。您不需要创建 $scope 对象,AngularJS 会根据您的模板层次结构正确且适当地为您实例化和配置它。然后 AngularJS 使用依赖注入的魔力使其可用于您的组件(稍后会详细介绍)。
Manual DOM changes vs. Data Binding
手动 DOM 更改与数据绑定
In jQuery you make all your DOM changes by hand. You construct new DOM elements programatically. If you have a JSON array and you want to put it to the DOM, you must write a function to generate the HTML and insert it.
在 jQuery 中,您可以手动更改所有 DOM。您以编程方式构建新的 DOM 元素。如果你有一个 JSON 数组并且你想把它放到 DOM 中,你必须编写一个函数来生成 HTML 并插入它。
In AngularJS you can do this too, but you are encouraged to make use of data binding. Change your model, and because the DOM is bound to it via a template your DOM will automatically update, no intervention required.
在 AngularJS 中,您也可以这样做,但我们鼓励您使用数据绑定。更改您的模型,因为 DOM 通过模板绑定到它,您的 DOM 将自动更新,无需干预。
Because data binding is done from the template, using either an attribute or the curly brace syntax, it's super easy to do. There's little cognitive overhead associated with it so you'll find yourself doing it all the time.
因为数据绑定是从模板完成的,使用属性或花括号语法,这非常容易。与此相关的认知开销很小,因此您会发现自己一直在这样做。
<input ng-model="user.name" />
Binds the input element to $scope.user.name. Updating the input will update the value in your current scope, and vice-versa.
将输入元素绑定到$scope.user.name。更新输入将更新当前范围内的值,反之亦然。
Likewise:
同样地:
<p>
{{user.name}}
</p>
will output the user name in a paragraph. It's a live binding, so if the $scope.user.namevalue is updated, the template will update too.
将在一个段落中输出用户名。这是一个实时绑定,所以如果$scope.user.name值更新,模板也会更新。
Ajax all of the time
一直以来的阿贾克斯
In jQuery making an Ajax call is fairly simple, but it's still something you might think twice about. There's the added complexity to think about, and a fair chunk of script to maintain.
在 jQuery 中,进行 Ajax 调用相当简单,但您可能仍需三思而后行。需要考虑额外的复杂性,以及需要维护的大量脚本。
In AngularJS, Ajax is your default go-to solution and it happens all the time, almost without you noticing. You can include templates with ng-include. You can apply a template with the simplest custom directive. You can wrap an Ajax call in a service and create yourself a GitHubservice, or a Flickrservice, which you can access with astonishing ease.
在 AngularJS 中,Ajax 是你默认的首选解决方案,它一直发生,几乎没有你注意到。您可以使用 ng-include 包含模板。您可以使用最简单的自定义指令应用模板。您可以将 Ajax 调用包装在一个服务中,并为自己创建一个GitHub服务或一个Flickr服务,您可以非常轻松地访问这些服务。
Service Objects vs Helper Functions
服务对象 vs 辅助函数
In jQuery, if we want to accomplish a small non-dom related task such as pulling a feed from an API, we might write a little function to do that in our closure. That's a valid solution, but what if we want to access that feed often? What if we want to reuse that code in another application?
在 jQuery 中,如果我们想要完成一个小的非 dom 相关的任务,比如从 API 中提取一个提要,我们可能会在我们的闭包中编写一个小函数来完成它。这是一个有效的解决方案,但如果我们想经常访问该提要怎么办?如果我们想在另一个应用程序中重用该代码怎么办?
AngularJS gives us service objects.
AngularJS 为我们提供了服务对象。
Services are simple objects that contain functions and data. They are always singletons, meaning there can never be more than one of them. Say we want to access the Stack Overflow API, we might write a StackOverflowServicewhich defines methods for doing so.
服务是包含函数和数据的简单对象。他们总是单身,这意味着他们永远不会超过一个。假设我们想要访问 Stack Overflow API,我们可能会编写一个StackOverflowService定义了这样做的方法。
Let's say we have a shopping cart. We might define a ShoppingCartService which maintains our cart and contains methods for adding and removing items. Because the service is a singleton, and is shared by all other components, any object that needs to can write to the shopping cart and pull data from it. It's always the same cart.
假设我们有一个购物车。我们可以定义一个 ShoppingCartService 来维护我们的购物车并包含添加和删除项目的方法。因为该服务是一个单例,并且由所有其他组件共享,所以需要的任何对象都可以写入购物车并从中提取数据。它总是同一个购物车。
Service objects are self-contained AngularJS components which we can use and reuse as we see fit. They are simple JSON objects containing functions and Data. They are always singletons, so if you store data on a service in one place, you can get that data out somewhere else just by requesting the same service.
服务对象是独立的 AngularJS 组件,我们可以根据需要使用和重用它们。它们是包含函数和数据的简单 JSON 对象。它们始终是单例的,因此如果您将服务上的数据存储在一个地方,您可以通过请求相同的服务将数据导出到其他地方。
Dependency injection(DI) vs. Instatiation - aka de-spaghettification
依赖注入(DI) 与 Instatiation - aka de-spaghettification
AngularJS manages your dependencies for you. If you want an object, simply refer to it and AngularJS will get it for you.
AngularJS 为你管理你的依赖。如果你想要一个对象,只需引用它,AngularJS 就会为你获取它。
Until you start to use this, it's hard to explain just what a massive time boon this is. Nothing like AngularJS DI exists inside jQuery.
在您开始使用它之前,很难解释这是多么巨大的时间恩赐。jQuery 中不存在像 AngularJS DI 这样的东西。
DI means that instead of writing your application and wiring it together, you instead define a library of components, each identified by a string.
DI 意味着不是编写应用程序并将其连接在一起,而是定义一个组件库,每个组件由一个字符串标识。
Say I have a component called 'FlickrService' which defines methods for pulling JSON feeds from Flickr. Now, if I want to write a controller that can access Flickr, I just need to refer to the 'FlickrService' by name when I declare the controller. AngularJS will take care of instantiating the component and making it available to my controller.
假设我有一个名为“FlickrService”的组件,它定义了从 Flickr 提取 JSON 提要的方法。现在,如果我想编写一个可以访问 Flickr 的控制器,我只需要在声明控制器时按名称引用“FlickrService”。AngularJS 将负责实例化组件并使其可用于我的控制器。
For example, here I define a service:
例如,这里我定义了一个服务:
myApp.service('FlickrService', function() {
return {
getFeed: function() { // do something here }
}
});
Now when I want to use that service I just refer to it by name like this:
现在,当我想使用该服务时,我只需按以下名称引用它:
myApp.controller('myController', ['FlickrService', function(FlickrService) {
FlickrService.getFeed()
}]);
AngularJS will recognise that a FlickrService object is needed to instantiate the controller, and will provide one for us.
AngularJS 会识别出需要一个 FlickrService 对象来实例化控制器,并且会为我们提供一个。
This makes wiring things together very easy, and pretty much eliminates any tendency towards spagettification. We have a flat list of components, and AngularJS hands them to us one by one as and when we need them.
这使得将事物连接在一起非常容易,并且几乎消除了任何碎片化的趋势。我们有一个简单的组件列表,当我们需要它们时,AngularJS 会将它们一一交给我们。
Modular service architecture
模块化服务架构
jQuery says very little about how you should organise your code. AngularJS has opinions.
jQuery 很少说明应该如何组织代码。AngularJS 有意见。
AngularJS gives you modules into which you can place your code. If you're writing a script that talks to Flickr for example, you might want to create a Flickr module to wrap all your Flickr related functions in. Modules can include other modules (DI). Your main application is usually a module, and this should include all the other modules your application will depend on.
AngularJS 为您提供了可以放置代码的模块。例如,如果您正在编写一个与 Flickr 对话的脚本,您可能想要创建一个 Flickr 模块来包装所有与 Flickr 相关的功能。模块可以包含其他模块 (DI)。您的主应用程序通常是一个模块,这应该包括您的应用程序将依赖的所有其他模块。
You get simple code reuse, if you want to write another application based on Flickr, you can just include the Flickr module and voila, you have access to all your Flickr related functions in your new application.
您可以获得简单的代码重用,如果您想编写另一个基于 Flickr 的应用程序,您可以只包含 Flickr 模块,瞧,您可以在新应用程序中访问所有与 Flickr 相关的功能。
Modules contain AngularJS components. When we include a module, all the components in that module become available to us as a simple list identified by their unique strings. We can then inject those components into each other using AngularJS's dependency injection mechanism.
模块包含 AngularJS 组件。当我们包含一个模块时,该模块中的所有组件都可以作为一个由其唯一字符串标识的简单列表供我们使用。然后我们可以使用 AngularJS 的依赖注入机制将这些组件相互注入。
To sum up
总结
AngularJS and jQuery are not enemies. It's possible to use jQuery within AngularJS very nicely. If you're using AngularJS well (templates, data-binding, $scope, directives, etc.) you will find you need a lotless jQuery than you might otherwise require.
AngularJS 和 jQuery 不是敌人。可以很好地在 AngularJS 中使用 jQuery。如果您使用AngularJS以及(模板,数据绑定,$范围,指令等),你会发现你需要很多少jQuery的比,否则你可能需要。
The main thing to realise is that your template drives your application. Stop trying to write big plugins that do everything. Instead write little directives that do one thing, then write a simple template to wire them together.
要意识到的主要事情是您的模板驱动您的应用程序。停止尝试编写可以做所有事情的大插件。而是编写一些只做一件事的小指令,然后编写一个简单的模板将它们连接在一起。
Think less about unobtrusive JavaScript, and instead think in terms of HTML extensions.
少考虑不引人注目的 JavaScript,而是考虑 HTML 扩展。
My little book
我的小书
I got so excited about AngularJS, I wrote a short book on it which you're very welcome to read online http://nicholasjohnson.com/angular-book/. I hope it's helpful.
我对 AngularJS 非常兴奋,我写了一本关于它的小书,非常欢迎你在线阅读http://nicholasjohnson.com/angular-book/。我希望它有帮助。
回答by Ulises
Can you describe the paradigm shift that is necessary?
你能描述一下必要的范式转变吗?
Imperative vs Declarative
命令式与声明式
With jQueryyou tell the DOM what needs to happen, step by step. With AngularJSyou describe what results you want but not how to do it. More on this here. Also, check out Mark Rajcok's answer.
使用jQuery,您可以一步一步地告诉 DOM 需要发生什么。使用AngularJS,你可以描述你想要的结果,而不是如何去做。更多关于这里。另外,请查看 Mark Rajcok 的回答。
How do I architect and design client-side web apps differently?
我如何以不同的方式构建和设计客户端 Web 应用程序?
AngularJS is an entire client-side framework that uses the MVCpattern (check out their graphical representation). It greatly focuses on separation of concerns.
AngularJS 是一个完整的客户端框架,它使用MVC模式(查看他们的图形表示)。它非常注重关注点的分离。
What is the biggest difference? What should I stop doing/using; what should I start doing/using instead?
最大的区别是什么?我应该停止做什么/使用什么;我应该开始做什么/使用什么?
jQueryis a library
jQuery是一个库
AngularJSis a beautiful client-side framework, highly testable, that combines tons of cool stuff such as MVC, dependency injection, data binding and much more.
AngularJS是一个漂亮的客户端框架,高度可测试,它结合了大量很酷的东西,比如 MVC、依赖注入、数据绑定等等。
It focuses on separation of concernsand testing (unit testingand end-to-end testing), which facilitates test-driven development.
它侧重于关注点和测试(单元测试和端到端测试)的分离,这有助于测试驱动的开发。
The best way to start is going through their awesome tutorial. You can go through the steps in a couple of hours; however, in case you want to master the concepts behind the scenes, they include a myriad of reference for further reading.
最好的开始方式是阅读他们很棒的教程。您可以在几个小时内完成这些步骤;但是,如果您想掌握幕后的概念,它们包含了大量可供进一步阅读的参考资料。
Are there any server-side considerations/restrictions?
是否有任何服务器端注意事项/限制?
You may use it on existing applications where you are already using pure jQuery. However, if you want to fully take advantage of the AngularJS features you may consider coding the server side using a RESTfulapproach.
您可以在已经使用纯 jQuery 的现有应用程序中使用它。但是,如果您想充分利用 AngularJS 的特性,您可以考虑使用RESTful方法对服务器端进行编码。
Doing so will allow you to leverage their resource factory, which creates an abstraction of your server side RESTful APIand makes server-side calls (get, save, delete, etc.) incredibly easy.
这样做将允许您利用他们的资源工厂,它创建了服务器端 RESTful API的抽象,并使服务器端调用(获取、保存、删除等)变得非常容易。
回答by Scott Rippey
To describe the "paradigm shift", I think a short answer can suffice.
为了描述“范式转变”,我认为一个简短的答案就足够了。
AngularJS changes the way you findelements
AngularJS 改变了你查找元素的方式
In jQuery, you typically use selectorsto find elements, and then wire them up:$('#id .class').click(doStuff);
在jQuery 中,您通常使用选择器来查找元素,然后将它们连接起来:$('#id .class').click(doStuff);
In AngularJS, you use directivesto mark the elements directly, to wire them up:<a ng-click="doStuff()">
在AngularJS 中,你使用指令直接标记元素,将它们连接起来:<a ng-click="doStuff()">
AngularJS doesn't need (or want) you to find elements using selectors - the primary difference between AngularJS's jqLiteversus full-blown jQueryis that jqLite does not support selectors.
AngularJS并不需要(或希望)你找到使用选择元素- AngularJS的之间的主要区别jqLite与全面的jQuery的是jqLite不支持选择。
So when people say "don't include jQuery at all", it's mainly because they don't want you to use selectors; they want you to learn to use directives instead. Direct, not select!
所以当人们说“根本不包含 jQuery”时,主要是因为他们不想让你使用选择器;他们希望你学会使用指令来代替。直接,不选择!
回答by Nick Manning
jQuery
jQuery
jQuery makes ridiculously long JavaScript commands like getElementByHerpDerpshorter and cross-browser.
jQuery 制作了非常长的 JavaScript 命令,比如getElementByHerpDerp更短的和跨浏览器的。
AngularJS
AngularJS
AngularJS allows you to make your own HTML tags/attributes that do things which work well with dynamic web applications (since HTML was designed for static pages).
AngularJS 允许您制作自己的 HTML 标签/属性,这些标签/属性可以很好地与动态 Web 应用程序配合使用(因为 HTML 是为静态页面设计的)。
Edit:
编辑:
Saying "I have a jQuery background how do I think in AngularJS?" is like saying "I have an HTML background how do I think in JavaScript?" The fact that you're asking the question shows you most likely don't understand the fundamental purposes of these two resources. This is why I chose to answer the question by simply pointing out the fundamental difference rather than going through the list saying "AngularJS makes use of directives whereas jQuery uses CSS selectors to make a jQuery object which does this and that etc....". This question does not require a lengthy answer.
说“我有 jQuery 背景,我如何在 AngularJS 中思考?” 就像说“我有 HTML 背景,我在 JavaScript 中如何思考?” 您提出问题的事实表明您很可能不了解这两种资源的基本用途。这就是为什么我选择通过简单地指出根本区别来回答这个问题,而不是通过列表说“AngularJS 使用指令,而 jQuery 使用 CSS 选择器来创建一个 jQuery 对象,该对象执行此操作等等......” . 这个问题不需要冗长的答案。
jQuery is a way to make programming JavaScript in the browser easier. Shorter, cross-browser commands, etc.
jQuery 是一种使在浏览器中编写 JavaScript 变得更容易的方法。更短的跨浏览器命令等。
AngularJS extends HTML, so you don't have to put <div>all over the place just to make an application. It makes HTML actually work for applications rather than what it was designed for, which is static, educational web pages. It accomplishes this in a roundabout way using JavaScript, but fundamentally it is an extension of HTML, not JavaScript.
AngularJS 扩展了 HTML,所以你不必<div>为了制作一个应用程序而把所有的地方都放在那里。它使 HTML 实际上适用于应用程序,而不是它的设计目的,即静态的教育网页。它使用 JavaScript 以一种迂回的方式实现了这一点,但从根本上说,它是 HTML 的扩展,而不是 JavaScript。
回答by Samuel
jQuery: you think a lot about 'QUERYing the DOM' for DOM elements and doing something.
jQuery:你想了很多关于DOM 元素的“查询DOM”并做一些事情。
AngularJS: THE model is the truth, and you always think from that ANGLE.
AngularJS:模型就是真理,你总是从那个角度思考。
For example, when you get data from THE server which you intend to display in some format in the DOM, in jQuery, you need to '1. FIND' where in the DOM you want to place this data, the '2. UPDATE/APPEND' it there by creating a new node or just setting its innerHTML. Then when you want to update this view, you then '3. FIND' the location and '4. UPDATE'. This cycle of find and update all done within the same context of getting and formatting data from server is gone in AngularJS.
例如,当您从服务器获取数据并打算在 DOM 中以某种格式显示时,在 jQuery 中,您需要 '1. FIND' 在 DOM 中要放置此数据的位置,即 '2. 通过创建新节点或仅设置其innerHTML 来更新/追加它。然后当你想更新这个视图时,你然后'3。查找'位置和'4。更新'。在从服务器获取和格式化数据的相同上下文中完成的查找和更新循环在 AngularJS 中消失了。
With AngularJS you have your model (JavaScript objects you are already used to) and the value of the model tells you about the model (obviously) and about the view, and an operation on the model automatically propagates to the view, so you don't have to think about it. You will find yourself in AngularJS no longer finding things in the DOM.
使用 AngularJS,你有你的模型(你已经习惯的 JavaScript 对象),模型的值告诉你模型(显然)和视图,模型上的操作会自动传播到视图,所以你不不必考虑。你会发现自己在 AngularJS 中不再在 DOM 中寻找东西。
To put in another way, in jQuery, you need to think about CSS selectors, that is, where is the divor tdthat has a class or attribute, etc., so that I can get their HTML or color or value, but in AngularJS, you will find yourself thinking like this: what model am I dealing with, I will set the model's value to true. You are not bothering yourself of whether the view reflecting this value is a checked box or resides in a tdelement (details you would have often needed to think about in jQuery).
换句话说,在 jQuery 中,您需要考虑 CSS 选择器,即div或td具有类或属性等的位置,以便我可以获取它们的 HTML 或颜色或值,但在 AngularJS 中,你会发现自己是这样想的:我在处理什么模型,我将模型的值设置为 true。您不会为反映此值的视图是复选框还是驻留在td元素中而烦恼(您经常需要在 jQuery 中考虑这些细节)。
And with DOM manipulation in AngularJS, you find yourself adding directives and filters, which you can think of as valid HTML extensions.
使用 AngularJS 中的 DOM 操作,您会发现自己添加了指令和过滤器,您可以将它们视为有效的 HTML 扩展。
One more thing you will experience in AngularJS: in jQuery you call the jQuery functions a lot, in AngularJS, AngularJS will call your functions, so AngularJS will 'tell you how to do things', but the benefits are worth it, so learning AngularJS usually means learning what AngularJS wants or the way AngularJS requires that you present your functions and it will call it accordingly. This is one of the things that makes AngularJS a framework rather than a library.
你会在 AngularJS 中体验的另一件事:在 jQuery 中你经常调用 jQuery 函数,在 AngularJS 中,AngularJS 会调用你的函数,所以 AngularJS 会“告诉你如何做事”,但好处是值得的,所以学习 AngularJS通常意味着学习 AngularJS 想要什么或 AngularJS 要求你展示你的函数的方式,它会相应地调用它。这是使 AngularJS 成为框架而不是库的原因之一。
回答by Dan
Those are some very nice, but lengthy answers.
这些是一些非常好的但冗长的答案。
To sum up my experiences:
总结一下我的经历:
- Controllers and providers (services, factories, etc.) are for modifying the data model, NOT HTML.
- HTML and directives define the layout and binding to the model.
- If you need to share data between controllers, create a service or factory - they are singletons that are shared across the application.
- If you need an HTML widget, create a directive.
- If you have some data and are now trying to update HTML... STOP! update the model, and make sure your HTML is bound to the model.
- 控制器和提供者(服务、工厂等)用于修改数据模型,而不是 HTML。
- HTML 和指令定义了模型的布局和绑定。
- 如果您需要在控制器之间共享数据,请创建一个服务或工厂——它们是跨应用程序共享的单例。
- 如果您需要 HTML 小部件,请创建一个指令。
- 如果您有一些数据并且现在正在尝试更新 HTML...停止!更新模型,并确保您的 HTML 绑定到模型。
回答by Anand
jQuery is a DOM manipulation library.
jQuery 是一个 DOM 操作库。
AngularJS is an MV* framework.
AngularJS 是一个 MV* 框架。
In fact, AngularJS is one of the few JavaScript MV* frameworks (many JavaScript MVC tools still fall under the category library).
事实上,AngularJS 是为数不多的 JavaScript MV* 框架之一(许多 JavaScript MVC 工具仍属于类别库)。
Being a framework, it hosts your code and takes ownership of decisions about what to call and when!
作为一个框架,它托管您的代码并决定调用什么以及何时调用!
AngularJS itself includes a jQuery-lite edition within it. So for some basic DOM selection/manipulation, you really don't have to include the jQuery library (it saves many bytes to run on the network.)
AngularJS 本身包含一个 jQuery-lite 版本。因此,对于一些基本的 DOM 选择/操作,您确实不必包含 jQuery 库(它可以节省许多字节以在网络上运行。)
AngularJS has the concept of "Directives" for DOM manipulation and designing reusable UI components, so you should use it whenever you feel the need of doing DOM manipulation related stuff (directives are only place where you should write jQuery code while using AngularJS).
AngularJS 有用于 DOM 操作和设计可重用 UI 组件的“指令”的概念,所以当你觉得需要做 DOM 操作相关的东西时你应该使用它(指令只是你在使用 AngularJS 时应该编写 jQuery 代码的地方)。
AngularJS involves some learning curve (more than jQuery :-).
AngularJS 涉及一些学习曲线(不仅仅是 jQuery :-)。
-->For any developer coming from jQuery background, my first advice would be to "learn JavaScript as a first class language before jumping onto a rich framework like AngularJS!" I learned the above fact the hard way.
-->对于任何具有 jQuery 背景的开发人员,我的第一个建议是“在跳到像 AngularJS 这样的丰富框架之前,将 JavaScript 作为一流语言学习!” 我通过艰难的方式了解到了上述事实。
Good luck.
祝你好运。
回答by Jin
They're apples and oranges. You don't want to compare them. They're two different things. AngularJs has already jQuery lite built in which allows you to perform basic DOM manipulation without even including the full blown jQuery version.
它们是苹果和橙子。你不想比较它们。他们是两种不同的东西。AngularJs 已经内置了 jQuery lite,它允许您执行基本的 DOM 操作,甚至不需要包含完整的 jQuery 版本。
jQuery is all about DOM manipulation. It solves all the cross browser pain otherwise you will have to deal with but it's not a framework that allows you to divide your app into components like AngularJS.
jQuery 是关于 DOM 操作的。它解决了所有跨浏览器的痛苦,否则您将不得不处理,但它不是一个允许您将应用程序划分为 AngularJS 等组件的框架。
A nice thing about AngularJs is that it allows you to separate/isolate the DOM manipulation in the directives. There are built-in directives ready for you to use such as ng-click. You can create your own custom directives that will contain all your view logic or DOM manipulation so you don't end up mingle DOM manipulation code in the controllers or services that should take care of the business logic.
AngularJs 的一个好处是它允许您在指令中分离/隔离 DOM 操作。有一些内置指令可供您使用,例如 ng-click。您可以创建自己的自定义指令,这些指令将包含您所有的视图逻辑或 DOM 操作,因此您最终不会在应该处理业务逻辑的控制器或服务中混合 DOM 操作代码。
Angular breaks down your app into - Controllers - Services - Views - etc.
Angular 将您的应用程序分解为 - 控制器 - 服务 - 视图 - 等等。
and there is one more thing, that's the directive. It's an attribute you can attach to any DOM element and you can go nuts with jQuery within it without worrying about your jQuery ever conflicts with AngularJs components or messes up with its architecture.
还有一件事,那就是指令。这是一个您可以附加到任何 DOM 元素的属性,您可以在其中使用 jQuery,而不必担心您的 jQuery 会与 AngularJs 组件发生冲突或弄乱其架构。
I heard from a meetup I attended, one of the founders of Angular said they worked really hard to separate out the DOM manipulation so do not try to include them back in.
我从我参加的一次聚会中听说,Angular 的一位创始人说他们非常努力地将 DOM 操作分离出来,所以不要试图将它们重新包括在内。

