假设我熟悉使用jQuery开发客户端应用程序,但是现在我想开始使用AngularJS。您能否描述必要的范式转换?以下是一些可以帮助您确定答案的问题:
我不希望在jQuery
和之间进行详细的比较AngularJS
。
1.不要设计您的页面,然后通过DOM操作对其进行更改
在jQuery中,您可以设计一个页面,然后将其动态化。这是因为jQuery是为增强而设计的,并且在此简单前提下得到了难以置信的增长。
但是在AngularJS中,您必须从头开始,牢记架构。您不必从“我拥有DOM的这个部分,而我想使其成为X”开始,而是必须从要完成的事情开始,然后开始设计应用程序,然后最后开始设计视图。
同样,不要以jQuery做X,Y和Z的想法开始,所以我只在模型和控制器的基础上添加AngularJS。这是 真的
,当你刚刚起步的,这就是为什么我总是建议新AngularJS开发完全不使用jQuery,至少直到他们习惯做的事情“角路”诱人。
我在这里和邮件列表中已经看到许多开发人员使用jQuery插件(包含150或200行代码)创建了这些精心设计的解决方案,然后将其粘贴到AngularJS中,并使用了一系列$apply
令人困惑和费解的回调和;但是他们最终使它起作用了!问题在于,在
大多数 情况下,可以用少量代码在AngularJS中重写jQuery插件,突然之间所有事情都变得容易理解和直接了。
底线是:解决时,首先“在AngularJS中思考”;如果您想不出解决方案,请询问社区;如果毕竟,有没有简单的解决方案, 然后
随意达到了jQuery。但是不要让jQuery成为拐杖,否则您将永远无法掌握AngularJS。
首先知道单页应用程序。它们 不是 网页。因此 ,除了 像客户端开发人员那样思考 之外 ,我们还需要像服务器端开发人员 那样
思考。我们必须考虑如何将应用程序划分为各个可扩展的可测试组件。
那你该 怎么 做呢?您如何“在AngularJS中思考”?以下是一些与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();
当我们仅查看视图时,并没有立即发现这里有任何功能。对于小型应用程序,这很好。但是对于非平凡的应用程序,事情很快就会变得混乱并且难以维护。
但是,在AngularJS中,视图是基于视图的功能的正式记录。我们的ul
声明看起来像这样:
<ul class="main-menu" dropdown-menu>
...
</ul>
两者的作用相同,但是在AngularJS版本中,任何查看模板的人都知道会发生什么。每当开发团队的新成员加入时,她都可以查看一下,然后 知道 有一个名为“
dropdownMenu
操作” 的指令。她不需要输入正确的答案或筛选任何代码。该视图告诉我们应该发生什么。干净得多。
刚接触AngularJS的开发人员经常会提出这样的问题:如何找到特定种类的所有链接并向它们添加指令。当我们回复时,开发人员总是为之震惊:您没有。但是,您不这样做的原因是,这就像一半的jQuery,一半的AngularJS,并且没有好处。这里的问题是开发人员试图在AngularJS上下文中“执行jQuery”。那永远行不通。该视图
是 官方记录。在指令之外(请参见下文),您永远 不会 更改DOM。并且 在视图 中应用 了 指令,因此意图很明确。
记住:不要设计,然后标记。您必须先架构师,然后进行设计。
到目前为止,这是AngularJS最令人敬畏的功能之一,并且消除了我在上一节中提到的执行DOM操作的大量需求。AngularJS将自动更新您的视图,因此您不必这样做!在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,我们如何测试逻辑?如果我们要更改演示文稿怎么办?
这有点凌乱和脆弱。但是在AngularJS中,我们可以这样做:
$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有点像模型。但是在AngularJS中,我们有一个单独的模型层,我们可以用它想要的任何方式进行管理,完全独立于视图。这有助于实现上述数据绑定,保持关注点分离,并引入更大的可测试性。其他答案都提到了这一点,因此我将其保留。
以上所有内容都与这个总体主题相关:将您的关注点分开。您的观点充当了将要发生的事情的正式记录(大部分情况下);您的模型代表您的数据;您有一个服务层来执行可重用的任务;您进行DOM操作并使用指令扩展视图;然后将它们与控制器粘合在一起。其他答案中也提到了这一点,我唯一要添加的内容就是可测试性,我将在下面的另一部分中进行讨论。
帮助我们分离关注点的是依赖注入(DI)。如果您来自服务器端语言(从Java到PHP),您可能已经熟悉此概念,但是如果您是来自jQuery的客户端人员,那么这个概念似乎从愚蠢到多余到时髦都不是。
。但事实并非如此。:-)
从广泛的角度来看,DI意味着您可以非常自由地声明组件,然后可以从任何其他组件中声明它们的实例,然后将其授予。您不必了解加载顺序,文件位置或类似内容。该功能可能不会立即可见,但我仅提供一个(常见)示例:测试。
假设在我们的应用程序中,我们需要一个服务,该服务通过REST
API以及本地存储(取决于应用程序状态)来实现服务器端存储。在我们的控制器上运行测试时,我们不需要与服务器通信- 毕竟,我们正在测试 控制器
。我们可以添加一个与原始组件同名的模拟服务,并且注入器将确保我们的控制器自动获得伪造的服务-我们的控制器不需要也不需要知道两者之间的区别。
说到测试…
这确实是第3部分有关体系结构的一部分,但它非常重要,因此我将其作为自己的顶层部分。
在您已经看到,使用或编写的所有jQuery插件中,有多少具有相应的测试套件?并不是很多,因为jQuery不太适合这种情况。但是AngularJS是。
在jQuery中,测试的唯一方法通常是使用示例/演示页面独立创建组件,我们的测试可以针对该示例/演示页面执行DOM操作。因此,我们必须分别开发一个组件,
然后 将其集成到我们的应用程序中。多么不便!很多时候,当使用jQuery开发时,我们选择迭代而不是测试驱动的开发。谁能责怪我们?
但是因为我们有关注点分离,所以我们可以在AngularJS中迭代进行测试驱动的开发!例如,假设我们要一个超级简单的指令在菜单中指示当前路线。我们可以在应用程序视图中声明我们想要的:
<a href="/hello" when-active>Hello</a>
好的,现在我们可以为不存在的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();
}));
当我们运行测试时,我们可以确认它失败。仅现在,我们应该创建指令:
.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' );
}
});
}
};
});
现在 , 我们的测试通过了 , 并且菜单按要求执行。我们的开发 既是 迭代的 又是 测试驱动的。邪恶的酷。
您会经常听到“仅在指令中进行DOM操作”。 这是必须的。 谨慎对待它!
但是让我们深入一点…
有些指令只是修饰视图中已经存在的内容(认为ngClass
),因此有时会立即进行DOM操作,然后基本完成。但是,如果一条指令就像一个“小部件”并具有一个模板,则它
也 应该尊重关注点的分离。也就是说,模板在链接和控制器功能中 也 应在很大程度上与其实现无关。
AngularJS附带了一整套工具,使这一过程变得非常容易。与ngClass
我们可以动态更新的类;
ngModel
允许双向数据绑定;ngShow
并以ngHide
编程方式显示或隐藏元素;还有更多-包括我们自己编写的内容。换句话说,我们可以在
没有 DOM操作的 情况下进行
各种出色的工作。DOM操作越少,指令的测试就越容易,指令的样式就越容易,将来更改就越容易,它们的重用性和可分发性就越高。
我看到很多使用指令作为投掷jQuery的地方的AngularJS新手。换句话说,他们认为“由于我无法在控制器中进行DOM操作,因此我会将代码放入指令中”。虽然这肯定好得多,但通常
仍然是错误的 。
想想我们在第3节中编写的记录器。即使将其放入指令中,我们 仍然 希望以“ Angular Way”方式进行操作。它 仍然
不需要任何DOM操作!很多时候需要进行DOM操作,但是它比您想像的 要 稀少得多!在对应用程序中的 任何位置
进行DOM操作之前,请问自己是否确实需要这样做。可能有更好的方法。
这是一个简单的示例,显示了我最常看到的模式。我们想要一个可切换的按钮。(注意:此示例有些人为设计,有点冗长,表示以完全相同的方式解决的更复杂的情况。)
.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);
});
}
};
});
这有一些问题:
angular.element
并且当我们的组件放入没有jQuery的项目时,它仍然可以工作。angular.element
)将 始终 使用jQuery,如果它是装的!因此我们不必使用$
-我们可以使用angular.element
。$
- element
传递给link
函数的jqLite元素 已经是 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都不会被触及,因此重构很容易。您可以随意更改模板,而无需触摸指令。而且,无论您进行什么更改,您的测试仍然可以通过。
w00t!
因此,如果指令不仅仅是类似jQuery的函数的集合,它们是什么?指令实际上 是HTML的扩展
。如果HTML不能做您需要做的事情,您可以编写一条指令来为您做,然后像使用HTML一样使用它。
换句话说,如果AngularJS没做什么开箱,认为球队如何完成它适合对符合ngClick
,ngClass
等。
甚至不使用jQuery。甚至不包含它。它会让你退缩。并且当您遇到问题时,您认为自己已经知道如何使用jQuery解决问题,因此在$
尝试之前,请尝试考虑如何在AngularJS范围内解决该问题。如果您不知道,请询问!20的19倍中,最好的方法不需要jQuery,并尝试使用jQuery解决它会为您带来更多工作。
问题内容: 假设我熟悉使用jQuery开发客户端应用程序,但是现在我想开始使用AngularJS。您能否描述必要的范式转换?以下是一些可以帮助您确定答案的问题: 我如何以不同的方式设计和设计客户端Web应用程序?最大的区别是什么? 我应该停止做什么/使用;我应该开始做什么/使用呢? 是否有服务器端注意事项/限制? 我不希望在和之间进行详细的比较。 问题答案: 1.不要设计页面,然后通过DOM操作对
使用指定背景颜色和指定背景颜色有什么区别? 片段#1 片段#2
背景色:rgb按照我的预期工作,但是背景:rgb填满了整个div。我看过的每个教程都告诉我,这两个基本相同,只是简写版可以有更多属性。 观看此视频以供参考。https://www.youtube.com/watch?v=10Q5D8kUMQo
问题内容: 我记得在AngularJS的视频中看到过这句名言,说应该一直使用。(点)在您的模型中。 好吧,我试图按照这个说法说我有 所以我认为这很有效 我使用了一个点,所以我认为这很好。 但是我有一些我认为不属于模型的属性,但也许我错了。例如,我有一个属性,可以使用ng- disable启用或禁用按钮,我已经使用点格式输入了此属性。基本上这样输入 我用它像 我是否应该将此模型作为“项目”的一部分?
本文向大家介绍Flex设置LinkButton的背景色有思路有源码,包括了Flex设置LinkButton的背景色有思路有源码的使用技巧和注意事项,需要的朋友参考一下 1、设计思路 由于Flex中没有设置LinkButton的背景色的属性,现在得从两个方面入手:第一,直接通过调用样式方法画出LinkButton的背景色;第二,设置LinkButton的背景图片。这里,讲述的是第一种方法 2、设计源
问题内容: 我想以 编程方式 删除ImageButton中的灰色背景。我尝试了多种删除方法,例如- 但是在实现它们时,我在触摸时不会在ImageButton上产生涟漪效果。(触摸时不突出显示)。 有什么方法可以消除背景但保留波纹效果或高光。 问题答案: 如果这个方法比我认为的有效,那么应该可以解决您的问题: http://codingdict.com/questions/141119