来源:http://blog.leezhong.com/tech/2010/11/29/javascript-arch.html

目前很多网站基本没有明确的前端架构,大多是服务端渲染视图页,输出到浏览器,再配合一些js,来进行交互。如果只是实现一些简单的效果,没有较复杂的逻辑,那么这种处理是合理的,尤其是有了jQuery之类的利器,js代码写起来甚至有种随心所欲的感觉。

但一旦网站要改版,或者随着网站的发展,逻辑变得越来越复杂,或者为了更好的用户体验,js要承担更多的任务,这时如果维持现状不变,那js就会变得越来越臃肿,越来越难维护。

解决之道就是采用模块化编程,将页面分成多个模块,模块之间互相独立,通过发布/订阅方式来进行模块间交互,从而使模块与模块解耦,也就是说移除一个模块不会对当前页面造成影响。

配合模板的话,可以让前端和后端程序员更高效地配合。前端只负责数据的显示与页面的交互,开发时,可以拟造数据,而不需要服务端程序。后端程序员也可以专注于提供更易用,稳定的接口,而不需要关心数据的展示。

yahoo的这个视频详细地阐述了前端模块化编程,大致摘录如下:

js架构的4个组成部分

  • 模块(Modules)
  • 沙箱(Sandbox)
  • 应用(App Core)
  • 类库(Base Lib)

模块(一切皆模块)

模块就像孩子一样,他们需要遵守一些规则才能保证不会到处惹麻烦

模块必须在沙箱里,无论条件多么苛刻

模块不知道页面到底是怎样的,他们只知道沙箱

模块之间要解耦

模块的规则

  • 管好自己

    • 只能调用自己的或沙箱的方法
    • 不要访问不属于自己的DOM节点
    • 不要访问非内置全局变量
  • 先申请,再使用
    • 你需要的任何东西,要向沙箱提出申请
  • 不要把玩具放得到处都是
    • 不要创建全局变量
  • 不要和陌生人说话
    • 不要直接引用其他模块

安全沙箱

沙箱要保证接口的一致性,模块调用时一定要有

模块只知道沙箱,其他的架构对模块而言是不存在的

沙箱就像一个安保员,知道哪些是模块可以调用的

沙箱的职责

  • 一致性

    • 接口一定要可靠
  • 安全性
    • 检测哪一部分是模块可以访问的
  • 交互
    • 将模块的请求发送到系统

多花些时间来设计沙箱接口,可以添加新方法,但不能移除,也不能修改已有方法

应用核心

应用核心负责模块间的交互

应用核心通知一个模块何时该初始化,何时该注销

应用核心处理错误

应用核心的任务

  • 管理模块的生存周期

    • 通知一个模块何时该初始化,何时该注销
  • 内部模块间的交互
    • 让模块尽可能解耦
  • 错误处理
    • 检测,报告错误
  • 可扩展
    • 任何可扩展的东西都不会过时

基本类库

理想状态下,只有应用核心知道使用了哪个类库

基本类库的任务

  • 浏览器兼容性
  • 常用的工具
    • 解析/序列化XML,JSON等等
    • 对象操作
    • DOM操作
    • Ajax操作
  • 提供底层的可扩展性

实践

我没有全部按照上面说的来实现,而是借鉴了部分pureMVC的思想,这样似乎更简单些。

概述

  • 一个模块对应页面的某一部分
  • 模块提供了所有Mediator可以调用的方法
  • 一个Mediator管理一个特定的模块
  • 模块只被Mediator调用,模块甚至不知道Mediator的存在
  • Mediator之间通过发布/订阅的方式进行交互

demo

模块基类(这里使用了John Resig的simple javascript inheritance)

var Module = Class.extend({
init: function(obj) {
this.name = obj.name;
this.tpl = obj.tpl ? $(obj.tpl).text() : $('#'+obj.name+'-tpl').text();
this.$el = obj.el ? $(obj.el) : $('#'+obj.name);
this.data = {};
},
getTplData: function(data) {
return this.data.tplData;
},
renderTpl: function(data) {
this.data.tplData = data;
//使用了Mustache模板引擎
var html = Mustache.to_html(this.tpl, data);
this.$el.html(html);
}
});

列表模块

var List = Module.extend({
// Module 提供方法供Mediator调用
hl: function($item, lock) {
var $lis = this.$el.find('li');
$lis.each(function(){
$(this).removeClass('hl');
if (lock) {
$(this).data('locked', false);
}
if (!lock && $(this).data('locked')) {
$(this).addClass('hl');
}
});
if (lock)
$item.data('locked', true);
$item.addClass('hl');
},
unhl: function($item) {
$item.removeClass('hl');
}
});

前面说了模块就是准备好方法,让Mediator调用。

列表Mediator

var ListMediator = Mediator.extend({
init: function(){
var self = this;
// 初始化Module
this.module =new List({
"name": "list"
});
// 绑定事件
self.module.$el.delegate('li', 'click', function(e){
e.preventDefault();
// 调用Module方法
self.module.hl($(this), true);
var index = self.module.$el.find('li').index($(this));
// 发布消息,所有监听该事件的方法将被触发
// 参数为object,方便以后添加键值对
$.publish(self.module.name+':click', {
"content": self.module.getTplData().list[index].content
});
}).delegate('li', 'mouseover', function(e){
self.module.hl($(this));
}).delegate('li', 'mouseout', function(e){
self.module.unhl($(this));
});
// 获取源数据,使用了$.proxy,创建特定的context
$.getJSON('data.json', $.proxy(function(data){
// 调用Module的方法
this.module.renderTpl(data);
// 发布数据已载入消息
$.publish(self.module.name+':loaded', data);
}, this));
}
});

可以把模块想像成Model,Mediator想像成Controller,这样就实现了高内聚,低耦合。每一个单元(模块+Mediator)都可以单独使用,也可以被移除,而不影响现有架构。

大型应用的javascript架构的更多相关文章

  1. Mysql在大型网站的应用架构演变

    原创文章,转载请注明: 转载自http://www.cnblogs.com/Creator/本文链接地址: Mysql在大型网站的应用架构演变 本文已经被多处转载,包括CSDN推荐以及码农周刊等等,阅 ...

  2. 转:Mysql在大型网站的应用架构演变

    原文来自于:http://www.cnblogs.com/Creator/p/3776110.html 原创文章,转载请注明: 转载自http://www.cnblogs.com/Creator/本文 ...

  3. ASP.NET开发的大型网站有哪些架构方式

    谈谈用ASP.NET开发的大型网站有哪些架构方式(成本) 在上篇文章里(http://www.cnblogs.com/ms0017/archive/2011/07/26/2117676.html),列 ...

  4. 大型电商业务架构 IT大咖说 - 大咖干货,不再错过

    大型电商业务架构 IT大咖说 - 大咖干货,不再错过 http://www.itdks.com/dakashuo/new/dakalive/detail/591

  5. Mysql在大型网站的应用架构演变(转)

    原文: Mysql在大型网站的应用架构演变 本文已经被多处转载,包括CSDN推荐以及码农周刊等等,阅读数超过5w+,回流到我博客流量的还是比较少,不过这不重要, 后续会分享更多技术,尽量试图把自己理解 ...

  6. Java 18套JAVA企业级大型项目实战分布式架构高并发高可用微服务电商项目实战架构

    Java 开发环境:idea https://www.jianshu.com/p/7a824fea1ce7 从无到有构建大型电商微服务架构三个阶段SpringBoot+SpringCloud+Solr ...

  7. 基于.NET的大型Web站点StackOverflow架构分析(转)

    Stack Overflow网址:http://stackoverflow.com/ 当前访问量:每月9500PV(每天300多万PV) 当前Alexa排名:149 所用.NET技术:C#.Visua ...

  8. .Net 大型分布式基础服务架构横向演变概述

    一. 业务背景 构建具备高可用,高扩展性,高性能,能承载高并发,大流量的分布式电子商务平台,支持用户,订单,采购,物流,配送,财务等多个项目的协作,便于后续运营报表,分析,便于运维及监控. 二. 基础 ...

  9. 解析大型.NET ERP系统架构设计 Framework+ Application 设计模式

    我对大型系统的理解,从数量上面来讲,源代码超过百万行以上,系统有超过300个以上的功能,从质量上来讲系统应该具备良好的可扩展性和可维护性,系统中的功能紧密关联.除去业务上的复杂性,如何设计这样的一个协 ...

随机推荐

  1. Uva 12889 One-Two-Three

      Your little brother has just learnt to write one, two and three, in English. He has written a lot ...

  2. Git_期末总结

    终于到了期末总结的时刻了! 经过几天的学习,相信你对Git已经初步掌握.一开始,可能觉得Git上手比较困难,尤其是已经熟悉SVN的童鞋,没关系,多操练几次,就会越用越顺手. Git虽然极其强大,命令繁 ...

  3. BTSync FREE vs BTSync PRO

    Although both BitTorrent Sync 2.0 FREE and PRO ensure high file transfer speed and ultimate security ...

  4. QQclient团队博客

    Windows 8 视频採集  http://impd.tencent.com/?p=25 句柄泄漏检測工具的实现原理 http://impd.tencent.com/?p=29

  5. 如何使用==操作符,Equals方法,ReferenceEquals方法,IEquatable接口比较2个对象

    "世界上不会有两片完全相同的树叶",这句话适用于现实世界.而在软件世界中,这句话变成了"世界上必须有两片完全相同的树叶",否则,很多事情无以为继. 当比较2个对 ...

  6. TIF、JPG图片手动添加地理坐标的方法

    题目:为TIF.JPG图片添加地理坐标/平面直角坐标. 图片来源:GOOGLE EARTH.(当然也可以是其他知道四角点坐标的图片) 截图工具:GEtscreen(此软件截图时可以自动生成图片四角点坐 ...

  7. 使用Dictionary泛型集合封装业务逻辑判断 z

    C#2.0 提供了Dictionary 泛型类,它提供了从一组键到一组值的映射.字典中的每个添加项都由一个值及其相关联的键组成.通过键来检索值的速度是非常快的,接近于 O(1),这是因为 Dictio ...

  8. 在oracle中查询已知表名的表中所有字段名,每个字段是否是主键,是否是外键,是否为空的sql语句

    查询表的所有列及其属性:select t.*,c.COMMENTS from user_tab_columns t,user_col_comments c where t.table_name = c ...

  9. 6 cocos2dx粒子效果,类图关系,系统原生粒子和自己定义粒子效果,粒子编译器软件,爆炸粒子效果,烟花效果,火焰效果,流星效果,漩涡粒子效果,雪花效果,烟雾效果,太阳效果,下雨效果

     1 粒子 演示样例 2 类图关系 3 系统原生粒子 CCParticleSystem 全部粒子系统的父类 CCParticleSystemPoint. CCParticleSystemQuad ...

  10. homogeneous clip space and NDC

    CVV  canonical view volume HCS homogeneous clip space NDC nomolized device coordinates pipeline 的 ge ...