-
Notifications
You must be signed in to change notification settings - Fork 762
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Angular沉思录(三)Angular中的模块机制 #17
Comments
赞,这个 module 机制是 Angular 工程化中的坑王。 |
嗯,不知道这个module部分当初是谁挖的坑,有那么多珠玉在前,还做得那么烂,应该拖出来打一顿,呵呵。 |
在 angular 早期的业务场景中,也不算是坑。用的人越来越多,变成了巨坑…… |
不能同意更多,开始的时候看到module,哎呦不错这个好!后来发现和RequireJS等等加载器配合都各种不顺畅,只好把所有的JS都在加载时候一块load进来完事儿 |
我们的做法是在定义module时,加入其他module的依赖;然后其他的module都只是定义一个module,仅此而已。如同上边components的例子,是不是可以这样: /** main.js **/
// require components.js
angular.module("our.app", ['components']);
/** components.js **/
return angular.module('components', []);
/** componentA.js **/
require(["components.js"], function(componentsModule) {
// 这样 往componentsModule上去“挂载”东西
componentsModule.xxx = xxx
}); 然后在需要的地方,利用 |
@dolymood 我明白你的意思,就是专门弄一些空壳子,这些js文件中,每个只放module的声明对吧,这个可以解决问题,但主module必须把所有的壳子module文件全部加载进来,并且在依赖中包含。真正的业务实现的js中,不能声明module,只能使用。这么一来,这些壳子就纯属浪费了,所以我觉得还不如不要,所有的都挂主module的名字下 |
我想知道.... angular干嘛搞这么个module. 我实在想不通, 除了可以使用别名注入之外, 毫无用处啊, 怪不得2.0没了 可喜可贺 |
"在一些angular最佳实践中,建议各业务模块使用module来组织业务单元,基于以上原因,我个人是不认同的,我推荐在下一级的controller,service,factory等东西上,使用标准AMD的那种方式定义名称,而彻底放弃module的声明,比如所有业务代码都适用同一个module。" 想想还真是, 但这样出错更难找出模块的问题, 我现在是有个主命名空间, 例如 模块appmain, 其他的模块为appmain.model, appmain.directives , appmain.components 这样. 我觉得angular的模块坑不吭看你怎么理解, angular 模块我感觉根本就不是amd,cmd这种规范, angular的模块其实和javascript 的代码结构, 文件加载, 依赖 关系都不大. angular的模块更像是功能的命名空间, 就是一个app 或一个网站是一个模块 这种概念, 有点像组件的命名空间, 而不是javascript代码的模块管理. module "模块"可以翻译为"项目" 更好理解, module 其实改成project可能更好. |
@jinwyp 如果只在自己的一个项目中,怎么搞都是可以的。你考虑把项目中的一个或多个部分拿出去在几个项目之间共享,尤其是这些公共部分要做懒加载的时候,就比较难受了。 |
@xufei 其次,动态加载机制的不是推荐方式,这可以说是 requirejs 的问题。其实 requirejs 一直都有这个问题,对于一些有自身的生命周期管理的框架,难以切入。在WEB JS框架设计上,生命周期管理应该形成一个闭环,有一些与 browser 事件绑定的生命周期节点,使用 requirejs 完全无法处理闭环。所以延迟加载不是 angular 的坑,而是 requirejs 的缺陷。 |
另外一篇文章在哪儿呢?@xufei |
所以模块复用的时候,服务不要用factory。应该使用provider可以合理控制作用域。但小型应用中,真不建议自己搞很多模块,一个模块完事儿就好。 |
@xufei 在app启动后动态去添加依赖还是有方法的,方法参照这个库ocLazyLoad |
@ chinfeng 非常同意你的观点。 当然楼主的担心是正确的,随着项目变的庞大,它就不能满足大家的期望了,庆幸的是angular团队及时果断的推出2.0 |
所以,前年我基于angular搞一个平台规划的时候,是这样的: 其中有一段:
意思就是,模块只存放内部的controller那些实现,依赖关系外置到这个管理平台(预期是类似npm)中,然后在构建的时候,给它生成这些module的配置。这样,如果有一天我们需要把目录整体调整,也不至于到处要修改这个模块名。 如果不这样,我们就面临这样: angular.module("aa.bb.cc").controller("aa.bb.cc.ControllerD", [...]) 这样的写法,然后模块如果需要做业务上的调整,比如下沉一级目录,这些controller上面的名称都得跟着改,否则就会出现物理路径和逻辑路径不一致,也容易出现冲突。 angular 1.x其实在合理规划下,是足够支撑大型项目的,但这个module机制反而制约了它在大型工程上的使用体验,所以沦为中小型方案。其他部分并没有这么严重的缺点。 @myst729 你看看 |
@xufei 又读了一遍,理解,是一种预期。其实你遇到的问题,相信大家也都遇到过,但是没有像你一样总结思考出来,所以感谢啊!关于楼主所提到的问题,有个ng-conf的视频,中间有一段提到说是Angular1.x的DI module的缺点: https://www.youtube.com/watch?v=_OGGsf1ZXMs&index=1&list=PLw5h0DiJ-9PB-vLe3vaNFLG-cTw0Wo7fw
|
angular最佳实践那一部分,使用ADM方式定义。 有具体的例子吗? |
“module不支持运行时添加依赖”,踩过坑的路过,顺便奉上解决办法http://www.cnblogs.com/wangmeijian/p/5020788.html |
Angular中的模块机制
module
在AngularJS中,有module的概念,但是它这个module,跟我们通常在AMD里面看到的module是完全不同的两种东西,大致可以相当于是一个namespace,或者package,表示的是一堆功能单元的集合。
一个比较正式的Angular应用,需要声明一个module,供初始化之用。比如说:
随后,可以在HTML中指定这个module:
这样,就是以这个div为基准容器,实例化了刚才定义的module。
或者,也可以等价地这样,在这里,我们很清楚地看到,module的意义是用于标识在一个页面中可能包含的多个Angular应用。
这样可以在同一个页面中创建同一module的不同实例。两个应用互不干涉,在各自的容器中运行。
module的依赖项
除此之外,我们可以看到,在module声明的时候,后面带一个数组,这个数组里面可以指定它所依赖的module。比如说:
然后对应的HTML是:
好了,注意到这个例子里面,创建了两个module,在页面上只直接初始化了moduleA,但是从moduleA的依赖关系中,引用到了moduleB,所以,moduleA下面的TestCtrl,可以像引用同一个module下其他service那样,引用moduleB中定义的service。
到这里,我们是不是就可以把module当作一种namespace那样的组织方式呢,很可惜,它远远没有想的那么好。
这种module真的有用吗?
看下面这个例子:
我们在moduleA和moduleB中,分别定义了两个A跟B,然后,在moduleC和moduleD的时候中,分别依赖这两个module,但是依赖的顺序不同,其他所有代码完全一致,再看看结果,会发现两边的结果居然是不一致的。
再看看moduleE,它自己里面有一个A,然后结果跟前两个例子也是不同的。
照理说,我们对module会有一种预期,也就是把它当作命名空间来使用,但实际上它并未起到这种作用,只是一个简单的复制,把依赖的module中定义的东西全部复制到自己里面了,后面进来的会覆盖前面的,比如:
整个覆盖过程没有任何提示。
我们可以把module设计的初衷理解为:供不同的开发团队,或者不同的业务模块做归类约束用,但实际上完全没有起到这种作用。结果,不得不在下级组织单元的命名上继续做文章,不然在多项目集成的时候,就要面临冲突的风险。
更多的坑
不仅如此,这种module机制还为大型应用造成了不必要的麻烦。比如说,module不支持运行时添加依赖,看下面的例子:
假设上面是一个组件库,集中存放于components.js中,我们要在自己的应用中使用,必须:
现在假设这个components.js较大,我们不打算在首页引入,想在某个时候动态加载,就会出现这样的尴尬局面:
关键问题就在于它不存在一个在our.app启动之后向其中添加some.components依赖的方式。我们预期的代码方式是类似这样:
也就是这段代码中注释掉的那句。但从现在看来,它基本没法做这个,因为他用的是复制的方式,而且对同名的业务单元不做提示,也就是可能出现覆盖了已经在使用的模块,导致同一个应用中的同名业务单元出现行为不一致的情况,对排错很不利。
在一些angular最佳实践中,建议各业务模块使用module来组织业务单元,基于以上原因,我个人是不认同的,我推荐在下一级的controller,service,factory等东西上,使用标准AMD的那种方式定义名称,而彻底放弃module的声明,比如所有业务代码都适用同一个module。详细的介绍,我会在另外一篇文章中给出。
此外,考虑到在前端体系中,JavaScript是需要加载到浏览器才能使用的,module的机制自身也至少应当包括异步加载机制,很可惜,没有。没有模块加载机制,意味着什么呢?意味着做大型应用有麻烦。这个可以用一些变通的方式去处理,在这里先不提了。
可以看到,Angular中的module并未起到预期作用,相反,还造成了一些麻烦。因此,我认为这是Angular当前版本中唯一一块弊大于利的东西,在2.0中,这部分已经做了重新规划,会把这些问题解决,也加入动态加载的考虑。
The text was updated successfully, but these errors were encountered: