AngularJS 没有angularjs 元素选择器器算不算一个缺点

当前访客身份:游客 [
已有文章 2283 篇
当前位置:
AngularJS 开发者最常犯的 10 个错误
英文原文:
0人收藏此文章,
推荐于 1年前 (共 16 段, 翻译完成于 10-07) ()
参与翻译(5人):
AngularJS是如今最受欢迎的JS框架之一,简化开发过程是它的目标之一,这使得它非常适合于元型较小的apps的开发,但也扩展到具有全部特征的客户端应用的开发。易于开发、较多的特征及较好的效果导致了较多的应用,伴随而来的是一些陷阱。本文列举了AngularJS的一些共同的易于也问题的地方,尤其是在开发一个app的时候。
1. MVC目录结构
AngularJS是一个缺乏较好的term的MVC框架,其models不像backbone.js中那样做为一个框架来定义,但其结构模式仍匹配的较好。当在一个MVC框架中作业时,基于文件类型将文件组合在一起是其共同的要求:
templates/
&&&&_login.html
&&&&_feed.html
&&&&app.js
&&&&controllers/
&&&&&&&&LoginController.js
&&&&&&&&FeedController.js
&&&&directives/
&&&&&&&&FeedEntryDirective.js
&&&&services/
&&&&&&&&LoginService.js
&&&&&&&&FeedService.js
&&&&filters/
&&&&&&&&CapatalizeFilter.js
&翻译的不错哦!
这样的布局,&尤其是对那些有 Rails 背景的人来说, 看起来挺合理. 可是当 app 变得越来越庞大的时候, 这样的布局结构会导致每次都会打开一堆文件夹.&无论你是用 Sublime, Visual Studio,&还是 Vim with Nerd Tree, 每次都要花上很多时间滑动滚动条浏览这个目录树来查找文件.
如果我们根据每个文件隶属的功能模块来对文件分组, 而不是根据它隶属的层:
&&&&app.js
&&&&&&&&_feed.html
&&&&&&&&FeedController.js
&&&&&&&&FeedEntryDirective.js
&&&&&&&&FeedService.js
&&&&Login/
&&&&&&&&_login.html
&&&&&&&&LoginController.js
&&&&&&&&LoginService.js
&&&&Shared/
&&&&&&&&CapatalizeFilter.js
那么查找某个功能模块的文件就要容易得多, 自然可以提高开发的速度. 也许把 html 文件跟 js 文件放在混合放在一起做法不是每个人都能认同. 但是起码它省下宝贵的时间.
&翻译的不错哦!
2、模块分组
一开始就将主模块中所有子模块展示出来是通常的做法。但是开始做一个小应用还好,但是做大了就不好管理了。
var&app&=&angular.module('app',[]);app.service('MyService',&function(){
&&&&//service&code});app.controller('MyCtrl',&function($scope,&MyService){
&&&&//controller&code});
一个比较好的办法是将相似类型的子模块分组:
var&services&=&angular.module('services',[]);services.service('MyService',&function(){
&&&&//service&code});var&controllers&=&angular.module('controllers',['services']);controllers.controller('MyCtrl',&function($scope,&MyService){
&&&&//controller&code});var&app&=&angular.module('app',['controllers',&'services']);
这个方法与上面那个方法效果差不多,但是也不很大。运用要分组的思想将使工作更容易。
var&sharedServicesModule&=&angular.module('sharedServices',[]);
sharedServices.service('NetworkService',&function($http){});
var&loginModule&=&angular.module('login',['sharedServices']);
loginModule.service('loginService',&function(NetworkService){});
loginModule.controller('loginCtrl',&function($scope,&loginService){});
var&app&=&angular.module('app',&['sharedServices',&'login']);
当创建一个大的应用时,所有模块可能不会放在一页里,但是将模块根据类型进行分组将使模块的重用能力更强。
&翻译的不错哦!
3 依赖注入
依赖注入是AngularJS最棒的模式之一。它使测试变得更加方便,也让它所依赖的对象变的更加清楚明白。AngularJS&对于注入是非常灵活的。一个最简单的方式只需要为模块将依赖的名字传入函数中:
var&app&=&angular.module('app',[]);app.controller('MainCtrl',&function($scope,&$timeout){
&&&&$timeout(function(){
&&&&&&&&console.log($scope);
&&&&},&1000);});
这里,很清楚的是MainCtrl依赖于$scope和$timeout。
直到你准备投入生产并压缩你的代码。使用UglifyJS,上面的例子会变成:
var&app=angular.module("app",[]);
app.controller("MainCtrl",function(e,t){t(function(){console.log(e)},1e3)})
现在AngularJS怎么知道MainCtrl依赖什么?AngularJS提供了一个非常简单的解决方案:把依赖作为一个字符串数组传递,而数组的最后一个元素是一个把所有依赖作为参数的函数。
app.controller('MainCtrl',&['$scope',&'$timeout',&function($scope,&$timeout){
&&&&$timeout(function(){
&&&&&&&&console.log($scope);
&&&&},&1000);}]);
接下来在压缩的代码中AngularJS也可以知道如何找到依赖:
app.controller("MainCtrl",["$scope","$timeout",function(e,t){t(function(){console.log(e)},1e3)}])
&翻译的不错哦!
3.1 全局依赖
通常在写AngularJS应用时会有一个对象作为依赖绑定到全局作用域中。这意味着它在任何AngularJS的代码中都可用,但这打破了依赖注入模型同时带来一些问题,特别是在测试中。
AngularJS把这些全局变量封装到模块中,这样它们可以像标准AngularJS模块一样被注入。
是很棒的库,它把Javascript代码简化成了函数模式,并且它可以被转化成一个模块:
var&underscore&=&angular.module('underscore',&[]);underscore.factory('_',&function()&{
&&return&window._;&//Underscore&must&already&be&loaded&on&the&page});var&app&=&angular.module('app',&['underscore']);app.controller('MainCtrl',&['$scope',&'_',&function($scope,&_)&{
&&&&init&=&function()&{
&&&&&&&&&&_.keys($scope);
&&&&&&init();}]);
它允许应用继续用AngularJS依赖注入的风格,也让underscore在测试的时候被交换出来。
这或许看上去不重要,像是一个无关紧要的工作,但如果你的代码正在使用use strict(应该使用),那么这就变得有必要了。&
&翻译的不错哦!
4 控制器膨胀
控制器是AngularJS应用中的肉和番茄。它很简单,特别是开始的时候,在控制器中放入过多的逻辑。控制器不应该做任何DOM操作或者有DOM选择器,这应该由使用ngModel的指令(directives)做的事。同样地,业务逻辑应该在服务(services)中,而不是 控制器。
数据也应该被存在服务(services)中,除非它已经和$scope关联。服务(services)是留存于整个应用生命周期的个体,同时控制器在应用各阶段间都是暂态的。如果数据被存在控制器中,那么当它被重新实例化的时候,就需要从其他地方抓取。即使数据被存储在localStorage中,获取数据也要比从Javascript变量中获取要慢几个数量级。
AngularJS在遵从简单责任原则(SRP)时工作地最好。如果控制器是视图和模型的协调者,那么它拥有的逻辑应该被最小化。这将使得测试变的更加简单。&&
&翻译的不错哦!
5 Service 和 Factory的区别
几乎每一个刚接触AngularJS的开发者,都会对这两个东西产生困惑。&虽然它们(几乎)实现了同样的效果,但真的不是语法糖。
这里是它们在 AngularJS 源码中的定义:
function&factory(name,&factoryFn)&{&return&provider(name,&{&$get:&factoryFn&});&}
function&service(name,&constructor)&{
&&&&return&factory(name,&['$injector',&function($injector)&{
&&&&&&return&$injector.instantiate(constructor);
从源码上看显然 service 函数只是调用 factory 函数,然后&factory 函数再调用&provider 函数。事实上,value、constant和decorator 也是 AngularJS 提供的对&provider 的封装,但对它们使用场景不会有这种困惑,并且文档描述也非常清晰。
那么Service 仅仅是单纯的调用了一次 factory 函数吗? 重点在 $injector.instantiate 中; 在这个函数里service会接收一个由$injector 使用new关键字去实例化的一个构造器对象。(原文:with in this&function&$injector creates a new instance of the service's constructor function.)&
&翻译的不错哦!
下面是完成同样功能的一个service和一个factory。
var&app&=&angular.module('app',[]);
app.service('helloWorldService',&function(){
&&&&this.hello&=&function()&{
&&&&&&&&return&"Hello&World";
app.factory('helloWorldFactory',&function(){
&&&&return&{
&&&&&&&&hello:&function()&{
&&&&&&&&&&&&return&"Hello&World";
当 helloWorldService&或者 helloWorldFactory中的任何一个注入到controller里面, 他们都有一个返回字符串"Hello World"的名称为 hello方法。&这个service 的构造函数只在声明时被实例化一次,并且在这个 factory 对象每次被注入时各种互相引用, 但这个&factory还是只是被实例化了一次。 所有的 providers 都是单例的。
既然都完成同样的功能,为什么会有这两种格式存在?factory比service略微更灵活一些,因为它们可以使用new关键字返回函数(原文:Factories offer slightly more flexibility than services because they can return functions which can then be new'd)。 在其他地方,从面向对象编程的工厂模式来说。 一个factory可以是一个用于创建其他对象的对象。
app.factory('helloFactory',&function()&{
&&&&return&function(name)&{
&&&&&&&&this.name&=&
&&&&&&&&this.hello&=&function()&{
&&&&&&&&&&&&return&"Hello&"&+&this.
&&&&&&&&};
这里有一个使用了前面提到的那个service和两个factory的controller 的例子。需要注意的是 helloFactory 返回的是一个函数,变量name的值是在对象使用new关键字的时候设置。
app.controller('helloCtrl',&function($scope,&helloWorldService,&helloWorldFactory,&helloFactory)&{
&&&&init&=&function()&{
&&&&&&helloWorldService.hello();&//'Hello&World'
&&&&&&helloWorldFactory.hello();&//'Hello&World'
&&&&&&new&helloFactory('Readers').hello()&//'Hello&Readers'
&&&&init();
&翻译的不错哦!
在刚入门时候最好只使用services.
Factory更加适用于当你在设计一个需要私有方法的类的时候使用:
app.factory('privateFactory',&function(){
&&&&var&privateFunc&=&function(name)&{
&&&&&&&&return&name.split("").reverse().join("");&//reverses&the&name
&&&&return&{
&&&&&&&&hello:&function(name){
&&&&&&&&&&return&"Hello&"&+&privateFunc(name);
在这个例子中privateFactory含有一个不能被外部访问的私有privateFunc函数。这种使用方式services也可以实现,但是使用Factory代码结构显得更加清晰。
6 不会使用 Batarang
&是用于开发和调试 AngularJS 应用的一个优秀的chrome浏览器插件。
Batarang 提供了模型浏览,可以查看Angular内部哪些模型已经绑定到作用域(scopes&)。可以用于需要在运行时查看指令中的隔离作用域(isolate scopes)绑定的值。
Batarang 还提供了依赖关系图。 对于引入一个未测试的代码库, 这个工具可以快速确定哪些services应该得到更多的关注。
最后, Batarang提供了性能分析。 AngularJS 虽然是高性能开箱即用, 但是随着应用自定义指令和复杂的业务逻辑的增长,有时候会感到页面不够流畅。使用 Batarang 的性能分析工具可以很方便的查看哪些functions 在digest 周期中占用了更多的时间。这个工具还可以显示出整个监控树(full&watch tree),当页面有太多的监控器(watch)时,这个功能就显得有用了。
&翻译的不错哦!
7 太多的watchers
正如上文中提到的,在外部AngularJS是很不错的。因为在一个循环消化中需要进行dirty检查,一旦watcher的数目超过2,000,循环会出现很明显的问题。(2,000仅是一个参考数,在1.3版本中AngularJS对循环消化有更为严谨的控制,关于这个有较为详细的叙述)
&这个IIFE(快速响应函数)可输出当前本页中的watcher的数目,只需将其复制到console即可查看详情。IIFE的来源跟Jared关于的回答是类似的。
(function&()&{&
&&&&var&root&=&$(document.getElementsByTagName('body'));
&&&&var&watchers&=&[];
&&&&var&f&=&function&(element)&{
&&&&&&&&if&(element.data().hasOwnProperty('$scope'))&{
&&&&&&&&&&&&angular.forEach(element.data().$scope.$$watchers,&function&(watcher)&{
&&&&&&&&&&&&&&&&watchers.push(watcher);
&&&&&&&&&&&&});
&&&&&&&&angular.forEach(element.children(),&function&(childElement)&{
&&&&&&&&&&&&f($(childElement));
&&&&&&&&});
&&&&f(root);
&&&&console.log(watchers.length);})();
使用这个,可以从Batarang的效率方面来决定watcher及watch tree的数目,可以看到在哪些地方顾在或哪些地方没有改变的数据有一个watch。
当有数据没有变化时,但在Angular中又想让它成为模板,可以考虑使用.Bindonce在Angular中仅是一个可能使用模板的指令,但没有增加watch的数目。
&翻译的不错哦!
8 审视$scope
Javascript的基于原型的继承和基于类的继承在一些细微的方面是不同的。通常这不是问题,但是差别往往会在使用$scope时出现。在AngularJS中每一个$scope都从它的父$scope继承过来,最高层是$rootScope。($scope在指令中表现的有些不同,指令中的隔离作用域仅继承那些显式声明的属性。)
从父级那里分享数据对于原型继承来说并不重要。不过如果不小心的话,会遮蔽父级$scope的属性。
我们想在导航栏上呈现一个用户名,然后进入登陆表单。
&div&ng-controller="navCtrl"&
&&&&span&{{user}}&/span&
&&&&div&ng-controller="loginCtrl"&
&&&&&&&&&span&{{user}}&/span&
&&&&&&&&&input&ng-model="user"&&/input&
&&&&/div&&/div&
&翻译的不错哦!
考你下:当用户在设置了ngModel的文本框中输入了值,哪个模板会被更新?是navCtrl,loginCtrl还是两者?
如果你选loginCtrl,那么你可能对原型继承的机理比较了解了。当寻找字面值时,原型链并没有被涉及。如果navCtrl要被更新的话,那么查找原型链是必要的。当一个值时对象的时候就会发生这些。(记住在Javascript中,函数、数组合对象都算作对象)
所以想要获得期望的效果就需要在navCtrl上创建一个对象可以被loginCtrl引用。
&div&ng-controller="navCtrl"&
&&&&span&{{user.name}}&/span&
&&&&div&ng-controller="loginCtrl"&
&&&&&&&&&span&{{user.name}}&/span&
&&&&&&&&&input&ng-model="user.name"&&/input&
&&&&/div&&/div&
现在既然user是一个对象了,原型链会被考虑进去,navCtrl的模板和$scope也会随着loginCtrl更新。
这可能看上去像一个设计好的例子,但当涉及到像ngRepeat那样会创建子$scope的时候问题就会出现。
&翻译的不错哦!
9 手工测试
虽然测试驱动开发可能不是每一个开发者都喜欢的开发方式,不过每次开发者去检查他们的代码是否工作或开始砸东西时,他们正在做手工测试。
没有理由不去测试一个AngularJS应用。AngularJS从一开始就是被设计地易于测试的。依赖注入和ngMock模块就是证据。核心团队开发了一些工具来讲测试带到另一个级别。
单元测试是一组测试集的基本元素,但随着应用复杂性的提高,集成测试会引出更多实际问题。幸运地是AngularJS核心团队提供了必要的工具。
“我们构建了Protractor,一个端对端的测试运行工具,模拟用户交互,帮助你验证你的Angular应用的运行状况。”
Protractor使用Jasmine测试框架来定义测试。Protractor为不同的页面交互提供一套健壮的API。
有其他的端对端工具,不过Protractor有着自己的优势,它知道怎么和AngularJS的代码一起运行,特别是面临$digest循环的时候。&&
&翻译的不错哦!
一旦使用Protractor写好了集成测试,测试需要被运行起来。等待测试运行特别是集成测试,会让开发者感到沮丧。AngularJS核心团队也感到了这个痛苦并开发了。
Karma是一个Javascript测试运行工具,可以帮助你关闭反馈循环。Karma可以在特定的文件被修改时运行测试,它也可以在不同的浏览器上并行测试。不同的设备可以指向Karma服务器来覆盖实际场景。
&翻译的不错哦!
10&jQuery的使用
jQuery 是个很不错的类库.&它将跨平台开发标准化. 在现代网页开发中具有很重要的地位.&虽然 jQuery 拥有许多强大的功能.&但是他的设计理念却与 AngularJS 大相径庭.
AngularJS 是用来开发应用框架的; jQuery 则是一个用来简化 HTML 文档对象遍历和操作, 事件处理, 动画以及 Ajax&使用的类库而已. 这是它们俩在本质上的区别. AngularJS 侧重点在于应用的架构, 而非仅仅是补充 HTML 网页的功能.
如文档所述 AngularJS 可以让你根据应用的需要对 HTML 进一步扩展. 所以, 如果想要深入的了解&AngularJS 应用开发, 就不应该再继续抱着 jQuery 的大腿. jQuery 只会把程序员的思维方式限制在现有的 HTML 标准里头.
&翻译的不错哦!
DOM操作应该出现在指令中,但这并不意味着一定要使用jQuery包装集。在使用jQuery前要考虑到一些功能AngularJS已经提供了。指令建立于相互之间,并可以创建有用的工具。
总有一天,使用jQuery库是必要的,不过从一开始就引入它无疑是一个错误。
AngularJS是一个很不错的框架,并且和它的社区一起发展着。符合习惯的AngularJS仍旧是一个正在发展的概念,但希望以上这些对于规划一个AngularJS应用时会出现的陷阱可以被避免。&&
&翻译的不错哦!
Batarang 不怎么好用。我现在希望的是谷歌的 Chrome Dev Editor 能支持 ng。AngularJS 有没有缺点?MVVM 框架中有比它更好的吗_百度知道
AngularJS 有没有缺点?MVVM 框架中有比它更好的吗
提问者采纳
写了这么多AngularJS代码,可以说我对AngularJS了解比较深入了。Backbone也是一个很热门的JS框架,我通读了一下它的API文档,大概了解了他的运行机制。Backbone很精巧,很强大。但对比AngularJS,我说说我看到的Backbone的缺点,由于接触时间短,可能会存在误解,见谅。Backbone的Model把服务器端的数据模型映射到浏览器端,绑定数据验证机制,并与相应的REST操作绑定,这样每个数据模型都变成了独立体,方便REST操作,却限制REST的灵活性。比如我要将10个todo批量标记成已完成,它会发出10个REST请求。Backbone的Model没有与UI视图数据绑定,而是需要在View中自行操作DOM来更新或读取UI数据,这点很奇怪。AngularJS与此相反,Model直接与UI视图绑定,Model与UI视图的关系,通过directive封装,AngularJS内置的通用directive,就能实现大部分操作了,也就是说,基本不必关心Model与UI视图的关系,直接操作Model就行了,UI视图自动更新。而Model数据验证、与服务器端的数据交互都是非常简单而自由的。
来自团队:
其他类似问题
为您推荐:
mvvm的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁AngularJS 没有元素选择器算不算一个缺点_百度知道
AngularJS 没有元素选择器算不算一个缺点
我有更好的答案
angular.element('#setButton').XXXXX&div&&button id='setButton' type=&button& class=&btn btn-success&/&确定&/div&
其他类似问题
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁AngularJS 有没有缺点?MVVM 框架中有比它更好的吗_百度知道
AngularJS 有没有缺点?MVVM 框架中有比它更好的吗
提问者采纳
其实应该说AngularJS没缺点所用项目适适合用AngularJSAngularJS主要目简化CRUD操作主重度前段项目发周期结构其本身处MVVM框架处:MVC应用界面发台逻辑操作解耦逻辑放Model面处理;C转化VM加入数据双向绑定减少部工作量缺点(或者适用):其实跟jQuery比较(虽严格说,jQuery其实js类库非框架)jQuery丰富Dom元素选择器Dom元素相关操作AngularJS面反复操作Dom元素实际跟MVVM初衷相背离(,AngularJS提供directive做元素操作)结论 AngularJS种MVVM前段框架适合量复杂界面元素操作应用比游戏等关于否比更:其实适合没谁更 AngularJS仅MVVM框架目标自定义扩展Html元素(directive)等等认错前段框架 算比较重度前段框架许考虑些轻量级框架Backbone, Ember等
其他类似问题
为您推荐:
模拟高尔夫的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁}

我要回帖

更多关于 angularjs 元素选择器 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信