JavaScript大型可扩展的设计模式

JavaScript大型可扩展模式:Patterns of Large-Scale JavaScript Applications // Speaker Deck

我们总是从很少几句Javascript开始,但是慢慢地一个JS文件有5千行代码了。

后来有了JQuery,使用$对DOM进行操作。业务逻辑经常隐藏在这些DOM操作代码中,如下:

代码中有各种事件,有模板和响应分析,都混淆在一起了。

如何做到可测试 可扩展伸缩和可维护呢?
这是很难的。

我们需要重新审视以DOM为核心的操作模型,DOM是全局的有状态的,因此难于测试和维护。

不能再有5千行代码在一个文件中,到处都是全局变量,我们要向后端学习。

我们如何使用JQuery?经验证明,代码难于测试是因为我们的设计水准需要提高。

首先我们需要将状态从DOM中剥离出来:
MVC模式正是将数据(Model模型状态)和DOM(View代表)进行分离,其中C代码一种Mediator模式,进行模型的输入输出协调。

但是MVC的C不只是这些,还有更多扩展选择。

MVC -- > MV*
这里星号代表有不同选择。

MVP:
这里的P代表将展现逻辑推送到展现者。

MVVM:
将模型直接暴露,这样能够直接管理和使用。

AngularJS是一种Model View Whatever框架,Whatever意味着Whatever works for you.

有了这些,我们还要在文件切分上考虑状态和DOM的分离:
有两种划分文件目录的方法:以功能Featrue和以层Layer。

这里推荐以功能Featrue划分,根据业务功能不同将一个大的JS文件切分到不同功能目录下的小文件中。这称为模块Module

模块是包含逻辑,小的,彼此解耦松耦合的,甚至可以重用,这样就可以测试的。

如果一个系统中的对象是和场景上下文无关,那么这个系统是容易的。

模块的规则:
不要在模块外部访问DOM。
不要创建全局变量。
不要访问全局变量或非原生的对象(静态变量等)

记住这些以后,还有很多路要走:

下一步是解决依赖。

如下图:

代码中有全局变量的DOM,那么这个JS方法能以测试和重用了。

而改为下面代码:

这个函数有了两个输入参数ajax和$el,避免了全局变量。

下面我们实现一个在html某个DOM地方(".user")显示用户图片或其他数据的功能:

首先我们需要分离视图和模型,明确视图View的职责,那么View的职责应该是什么? 一个View只应该和一个Html元素及其这个元素以内有关。

举例,模型代码如下:


//这里假设模型User只有一个简单字段图片
var user={image:'http:
//example.com/image.png'}

视图View代码如下:

var UserView = function(el, user){
this.el = el;
this.user = user;
};

var view = new userView($('.user'), user);

UserView这个视图职责只和el这个html元素($('.user'))有关。
让我们增加职责行为如下:


UserView.prototype.showImage= function(){
this.el.append('<img src=' + this.user.image + '>');
};

那么我们现在可以做改变DOM的事情:
view.showImage();


[该贴被banq于2013-06-19 19:52修改过]
[该贴被admin于2013-06-22 15:31修改过]


[该贴被admin于2013-06-22 15:35修改过]
[该贴被admin于2013-06-22 15:36修改过]

[该贴被admin于2013-06-22 15:36修改过]

[该贴被admin于2013-06-22 15:37修改过]
[该贴被admin于2013-06-22 15:39修改过]

下面我们继续解决依赖,进入依赖注入,使用AngularJS可以容易解决依赖注入:

上面解决了代码的依赖,使用AMD可解决文件的依赖:


define['jquery'], function($){
return function(){};
});

如果依赖其他包怎么办?
使用Bower,如下图:


[该贴被banq于2013-06-19 19:55修改过]

javascript是一种弱类型语言,其开发过程中规范的意义相对于java、C之类强类型语言更加重要,常常会出现一个人无法看懂另外一人开发的javascript代码。

构建javascript大型应用的关键在于"组件化“,js代码直接与html标签耦合的做法是极其糟糕的。

图裂了