soma.js, infuse.js, Nervenet

上一篇日志中,我介绍了Nervenet的创作思路。虽然JavaScript有着各种各样的先天不足,但是,运气也是实力的一部分,所以广大开发者只有用各种手法去适应它、改良它。应该说大家干得很棒,我也想贡献自己的力量,于是创造了Nervenet,希望解决我在开发中遇到的各种问题。

就在我写完Nervenet初版的时候,偶然看到MVC框架soma.js的介绍,发现跟我的思路很相像(其中用到的IoC类库:infuse.js,也是他们开发的)。于是仔细研究了一番,学到不少东西。今天我准便拿Nervenet和它们分析对比一下。

soma.js

我自认是个不喜欢“重复发明轮子”的人,于是看到出发点和实现方式如此接近的框架,不免一惊,心说果然世界足够大,持同样想法的人非常多。不知道soma.js的作者有没有用过robotlegs,二者的API真的很像(也许是mvc框架的标配吧,我没看过相关介绍)。我最初也希望引入robotlegs的做法来改善JavaScript编程体验,不过在反复思考后,觉得并不需要全部移植,比如mediator。在Flash里,新的影片剪辑被添加到舞台上时会触发Event.ADDED事件,可以被robotlegs侦听;同时,所有mc都是Sprite的子类,可以使用类名作为索引来创建需要的mediator。而到了JavaScript方面,Dom节点发生变化并不会触发事件;添加的Dom节点也没有类的关系,所以这里的mediator只能我们自行创建,这样其实也就没什么实质性的好处了。

另一个不太需要移植的是Command类。在MVC框架中,它的功能基本就是响应全局事件,进行相应的处理,很多时候只要实现execute方法就好。ActionScript 3在面向方向上做的比较充分,代码都会封装成类,于是Command里还可以放一些helper类型的函数;到了JavaScript这儿就显得不太合适了,既没有强继承关系也没有类型检查,甚至连类的实现都不完整,helper也可以用闭包实现,如果一样搞成类来处理,只是凭空加重了对代码的限制,在我看来有点得不偿失了。

所以我在Nervenet中并没有把robotlegs的功能都移植,而是选取部分比较重要一定会用的实现了。(代码参看测试用例,这里不贴了)

infuse.js

接着再说infuse.js。我一开始准备直接给对象加上app或者context或者injector属性,但是一直觉得这样太过简单粗暴;看过源码发现他们比我略微温柔一点,先遍历对象的属性,如果map了同名属性,就注入进去——仔细想想这差不多是另一种粗暴吧,不由分说的注入同名属性,如果代码不是针对infuse.js写的,可能会产生更多问题。不过我还是学习了这种做法,并进行了一些改造:如果对象属性中有以“$”(可配置)开头的同名属性,就注入。有了这样的规则,新写代码有理可依,改动代码也会比较放心,阅读代码时也有利于识别本身属性和注入属性。

JavaScript没有类型检查,但是在日常开发中难免遇到多个类的实例适合同一个名字,比如model、remote之类的,如果在注入时能自动选择合适的类型,那自然是极好的。于是我想到利用变量声明时的初始值,把类名包括命名空间写进去,作为类型说明,就可以在注入时自动选择合适的类型了。

代码请看测试用例inject部分。

值得一提的是,infuse.js中每个函数都对参数进行了充分的验证,很值得学习,不过我目前还是偷懒只验证了很少一部分。

依赖管理和代码加载

依赖管理和代码加载也是我力图实现的功能,虽然看起来和架构无关,不过在操作层面上,还是比较合拍的。因为我们总要有一个入口函数,比如jQuery中的$(function () {});,通过分析入口函数,就能得到依赖关系,继而可以实现依赖管理和代码加载,这样丝毫不会影响代码架构。目前我也正是这么做的。

不过这种“自然”的代码书写方式也会给加载带来难度。无论AMD还是CMD,都会把代码以函数的形式封装起来,在依赖处理完成后执行;而这种自然的方式,就要求每段代码执行前依赖都已经加载了,所以只能用Ajax把代码以文本的形式加载下来,分析依赖,继续加载,直至全部完成;在按照依赖关系放入script标签执行。如此一来,执行的代码是不允许依赖关系嵌套的,那么,以闭包来实现私有属性和方法的做法就行不通了。这点我还在思考解决方案。

使用方式参看测试用例

总结

目前Nervenet已经初步完成,我正在编写入门文档,并将其应用到实际项目中进行测试。这些完成后将发布0.1版。目前市面上有一些做法很接近的框架,不过具体实现上还有差异,孰优孰劣也有待验证。我会尽量解决各种开发中的痛点。

如果您觉得文章内容对您有用,不妨支持我创作更多有价值的分享:


已发布

分类

,

来自

评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据