Yui3在美团3. • / spring
http://shangchun.net
springuper@gmail.com
4. • / spring
http://shangchun.net
springuper@gmail.com
• 2010 12
5. • / spring
http://shangchun.net
springuper@gmail.com
• 2010 12
•
8. • YUI3
YUI3
•
Combo Loading
18. Chaining Selector
AOP YUI3
Loader
OOP
22. var Y = YUI();
YUI.add(‘test’, function(Y) { Y.use(‘test’, function(Y) {
Y.sayHello = function() { Y.sayHello(); // alert
alert(‘Hello, world!’); });
}; YUI().use(function(Y) {
}); Y.sayHello(); // error
});
23. add
YUI.prototype.add = function(name, fn, details) {
// register on the global object YUI
YUI.Env.mods[name] = {
name: name,
fn: fn,
details: details || {}
};
return this;
};
YUI.add = YUI.prototype.add;
24. use
YUI.prototype.use = function() {
var Y = this, r = [],
args = Array.prototype.slice.call(arguments, 0),
callback = args[args.length - 1],
process = function(names) { ... };
args.pop();
process(args); // calculate sorted full module list r
Y._attach(r); // add the apis to Y
callback(Y);
return this;
};
32. YUI3
DOM Node
Core Event OOP
Seed YUI
33. YUI3
Component Widget Base
Framework Attribute Plugin
DOM Node
Core Event OOP
Seed YUI
34. YUI3
Drag & Drop Animation
Component IO Cookie JSON ...
Component Widget Base
Framework Attribute Plugin
DOM Node
Core Event OOP
Seed YUI
49. javascript
mt-base w-base w-table
Core w-autocomplete ...
Base & Frame YUI3
50. javascript
Site Core mis-base www-base ...
mt-base w-base w-table
Core w-autocomplete ...
Base & Frame YUI3
51. javascript
mis-deal mis-order
Site App finance-pay stat-compete ...
Site Core mis-base www-base ...
mt-base w-base w-table
Core w-autocomplete ...
Base & Frame YUI3
55. www-base mis-base w-base
mt-base
yui node event io ...
56. www-base mis-base w-base w-autocomplete ...
mt-base vendor
yui node event io ...
57. mis-order mis-misc ...
www-base mis-base w-base w-autocomplete ...
mt-base vendor
yui node event io ...
60. core
www
static mis
finance
vendor
...
62. mt.js [mt-base] w-base.js [w-base]
core w-tab.js [w-tab] w-date.js [w-date] ...
www in the near future
static mis
finance
vendor
...
63. mt.js [mt-base] w-base.js [w-base]
core w-tab.js [w-tab] w-date.js [w-date] ...
www in the near future
base.js [mis-base] deal.js [mis-deal]
static mis js order.js [mis-order] misc.js [mis-misc]
finance
vendor
...
64. mt.js [mt-base] w-base.js [w-base]
core w-tab.js [w-tab] w-date.js [w-date] ...
www in the near future
base.js [mis-base] deal.js [mis-deal]
static mis js order.js [mis-order] misc.js [mis-misc]
finance js pay.js [finance-pay]
vendor
...
65. mt.js [mt-base] w-base.js [w-base]
core w-tab.js [w-tab] w-date.js [w-date] ...
www in the near future
base.js [mis-base] deal.js [mis-deal]
static mis js order.js [mis-order] misc.js [mis-misc]
finance js pay.js [finance-pay]
vendor js jquery.min.js zeroClipboard.js ...
...
67. var M = window.M || {};
M._YUI = YUI;
M.add = function() {
M._YUI.add.apply(M._YUI, arguments);
return this;
};
M.use = function() {
var instance = M._YUI(YUI_META);
instance.use.apply(instance, arguments);
return this;
};
68. // static/mis/js/deal.js
(function() {
M.add(‘mis-deal’, function(Y) {
var $MIS = Y.mt.mis, isIE = Y.UA.ie ... // shortcut
var CONST = ‘const value‘ ... // const
Y.namespace(‘mt.mis.Deal’);
Y.mt.mis.Deal = {
editInfo:function(param) { ... }
};
}, ‘1.0.0’, { requires:M.Groups[‘mis’][‘modules’][‘deal’].requires });
})();
69. // helper/FileHelper.php
private static $groups = array(
‘core’ => array(...),
‘www’ => array(...),
‘mis’ => array(
‘mis-deal’ => array(
‘path’ => ‘mis/js/deal.js’,
‘requires’ => array(‘mis-base’, ‘w-tab’),
),
),
...
);
71. Combo
Minify (BSD, http://code.google.com/p/minify/)
// debug
FirePHP
// bad request header, CDN caches 400
$min_serveOptions[‘badRequestHeader’] = ‘HTTP/1.0 404 Not Found’;
// stop minifiers
$min_serveOptions[‘minifiers’] [‘application/x-javascript’] = null;
$min_serveOptions[‘minifiers’] [‘text/css’] = null;
76. Loader
// php frame
$loader = new YUILoader(
FileHelper::YUI3_VERSION,
FilerHelper::getMTModules()
);
// template
$loader->misInit(‘mis-deal’, “
Y.mt.mis.Deal.editInfo(‘. $status. ’, ‘ . $modReason. ’);
“);
77. Loader
// php frame
$loader = new YUILoader( PHP Loader
FileHelper::YUI3_VERSION,
FilerHelper::getMTModules()
);
// template
$loader->misInit(‘mis-deal’, “
Y.mt.mis.Deal.editInfo(‘. $status. ’, ‘ . $modReason. ’);
“);
82. •
• YUI3 - below the surface Luke Smith
• YUI2 YUI3
•
Editor's Notes 非常荣幸和大家一起分享我们团队在YUI3方面的一些实践。\n 我叫尚春,他们都叫我春哥。这里是我的博客和email。\n我在2010年12月11日毕业后进入美团工作,到现在已有7个多月的工作经验。\n这段时间,在师傅的指导下迅速成长,对前端的认识不断深入。\n 我叫尚春,他们都叫我春哥。这里是我的博客和email。\n我在2010年12月11日毕业后进入美团工作,到现在已有7个多月的工作经验。\n这段时间,在师傅的指导下迅速成长,对前端的认识不断深入。\n 我叫尚春,他们都叫我春哥。这里是我的博客和email。\n我在2010年12月11日毕业后进入美团工作,到现在已有7个多月的工作经验。\n这段时间,在师傅的指导下迅速成长,对前端的认识不断深入。\n 此次分享主要涉及两方面的内容。首先是关于选择YUI3作为基础库的原因,这里我们重点介绍下YUI3的模块机制;然后我们主要就我们实际迁移中遇到的一些挑战作详细表述,例如划分模块、加载策略等。\n 此次分享主要涉及两方面的内容。首先是关于选择YUI3作为基础库的原因,这里我们重点介绍下YUI3的模块机制;然后我们主要就我们实际迁移中遇到的一些挑战作详细表述,例如划分模块、加载策略等。\n 简要介绍下我们的前端团队。\n我们是一支小而精悍的队伍,为美团网视觉界面和用户交互提供充足动力。\n我们崇尚的是“快”,通过快速开发、快速部署、快速迭代来完成任务、优化功能。\n我们坚持“在行进中开火”,宁可十年不将军,不可一日不拱卒。\n我们认为做事不应该准备太多,一定要先做起来,然后发现不足并不断改进。\n这些信条可能更加适合我们这样的小团队。\n\n 简要介绍下我们的前端团队。\n我们是一支小而精悍的队伍,为美团网视觉界面和用户交互提供充足动力。\n我们崇尚的是“快”,通过快速开发、快速部署、快速迭代来完成任务、优化功能。\n我们坚持“在行进中开火”,宁可十年不将军,不可一日不拱卒。\n我们认为做事不应该准备太多,一定要先做起来,然后发现不足并不断改进。\n这些信条可能更加适合我们这样的小团队。\n\n 简要介绍下我们的前端团队。\n我们是一支小而精悍的队伍,为美团网视觉界面和用户交互提供充足动力。\n我们崇尚的是“快”,通过快速开发、快速部署、快速迭代来完成任务、优化功能。\n我们坚持“在行进中开火”,宁可十年不将军,不可一日不拱卒。\n我们认为做事不应该准备太多,一定要先做起来,然后发现不足并不断改进。\n这些信条可能更加适合我们这样的小团队。\n\n 我们首先要回答的问题是:为什么选择YUI3。第一个原因,我们原来采用的是YUI2。作为YUI团队的作品,YUI2非常正统、稳定。第二个原因,YUI团队已经把重心转移到YUI3,基本不再维护YUI2。但这都不是最有说服力的原因。\n 我们首先要回答的问题是:为什么选择YUI3。第一个原因,我们原来采用的是YUI2。作为YUI团队的作品,YUI2非常正统、稳定。第二个原因,YUI团队已经把重心转移到YUI3,基本不再维护YUI2。但这都不是最有说服力的原因。\n 最为重要的原因是YUI3本身,它足够的优秀。\nYUI3具有很多新的特性,例如模块机制、选择器的全面应用、更强大的自定义事件、组件框架等等。\n如果说YUI2是库时代杰出典范之一的话,YUI3就是框架时代一颗璀璨的明星。\n 最为重要的原因是YUI3本身,它足够的优秀。\nYUI3具有很多新的特性,例如模块机制、选择器的全面应用、更强大的自定义事件、组件框架等等。\n如果说YUI2是库时代杰出典范之一的话,YUI3就是框架时代一颗璀璨的明星。\n 时间有限,我们重点介绍下YUI3的模块机制。\n模块是YUI3最大的变化,没有之一。这一底层设计机制改变了原有YUI2时代的规则。它为我们带来了自动加载、沙箱、combo等等特性,解放生产力的同时,提高了多人协作上的便利。\n使用YUI3添加模块、调用模块比较简单。\n 时间有限,我们重点介绍下YUI3的模块机制。\n模块是YUI3最大的变化,没有之一。这一底层设计机制改变了原有YUI2时代的规则。它为我们带来了自动加载、沙箱、combo等等特性,解放生产力的同时,提高了多人协作上的便利。\n使用YUI3添加模块、调用模块比较简单。\n 时间有限,我们重点介绍下YUI3的模块机制。\n模块是YUI3最大的变化,没有之一。这一底层设计机制改变了原有YUI2时代的规则。它为我们带来了自动加载、沙箱、combo等等特性,解放生产力的同时,提高了多人协作上的便利。\n使用YUI3添加模块、调用模块比较简单。\n 我们把源码进行适当简化,主要理解一下内部的机制。\nYUI构造器的add方法是这样定义的,即将模块的信息注册在YUI构造器的静态属性Env中。\n YUI的use方法主要流程是:\n计算调用模块所依赖的所有模块,\n将这些模块进行排序并输出,\n通过attach方法将这些模块的api依次捆绑在YUI实例(沙箱)上\n将载满api的YUI实例传递到回调函数中。\n 与直接嵌入script标签相比,模块的特点有:1,注册模块与调用模块分离,两者不是紧密耦合关系。2,所有模块都加载并绑定后才会执行回调函数,多个use间是异步关系。但,当所有模块都具备的情况下,多个use又是同步关系。3,通过实例绑定调用模块的api,实现了一种简便的沙箱机制。这一机制有利于协同开发。4,在模块定义时的一些元信息将所有模块有序组织起来,形成一个系统。\n 与直接嵌入script标签相比,模块的特点有:1,注册模块与调用模块分离,两者不是紧密耦合关系。2,所有模块都加载并绑定后才会执行回调函数,多个use间是异步关系。但,当所有模块都具备的情况下,多个use又是同步关系。3,通过实例绑定调用模块的api,实现了一种简便的沙箱机制。这一机制有利于协同开发。4,在模块定义时的一些元信息将所有模块有序组织起来,形成一个系统。\n 与直接嵌入script标签相比,模块的特点有:1,注册模块与调用模块分离,两者不是紧密耦合关系。2,所有模块都加载并绑定后才会执行回调函数,多个use间是异步关系。但,当所有模块都具备的情况下,多个use又是同步关系。3,通过实例绑定调用模块的api,实现了一种简便的沙箱机制。这一机制有利于协同开发。4,在模块定义时的一些元信息将所有模块有序组织起来,形成一个系统。\n 与直接嵌入script标签相比,模块的特点有:1,注册模块与调用模块分离,两者不是紧密耦合关系。2,所有模块都加载并绑定后才会执行回调函数,多个use间是异步关系。但,当所有模块都具备的情况下,多个use又是同步关系。3,通过实例绑定调用模块的api,实现了一种简便的沙箱机制。这一机制有利于协同开发。4,在模块定义时的一些元信息将所有模块有序组织起来,形成一个系统。\n YUI3的所有模块分为四个层级,它们构成了YUI3的架构。\n1,最底层是种子文件YUI,它定义了YUI构造器以及yui模块,主要包括Lang,UA,封装的Array, Object, 以及Get等等。\n2,第二层为核心工具层,主要是一些工具模块,例如DOM,Node,Event\n3,第三层为组件框架层,主要是为构建组件提供丰富灵活的机制\n4,第四层为组件层,包括了IO,JSON,Animation等重要模块\n YUI3的所有模块分为四个层级,它们构成了YUI3的架构。\n1,最底层是种子文件YUI,它定义了YUI构造器以及yui模块,主要包括Lang,UA,封装的Array, Object, 以及Get等等。\n2,第二层为核心工具层,主要是一些工具模块,例如DOM,Node,Event\n3,第三层为组件框架层,主要是为构建组件提供丰富灵活的机制\n4,第四层为组件层,包括了IO,JSON,Animation等重要模块\n YUI3的所有模块分为四个层级,它们构成了YUI3的架构。\n1,最底层是种子文件YUI,它定义了YUI构造器以及yui模块,主要包括Lang,UA,封装的Array, Object, 以及Get等等。\n2,第二层为核心工具层,主要是一些工具模块,例如DOM,Node,Event\n3,第三层为组件框架层,主要是为构建组件提供丰富灵活的机制\n4,第四层为组件层,包括了IO,JSON,Animation等重要模块\n YUI3的所有模块分为四个层级,它们构成了YUI3的架构。\n1,最底层是种子文件YUI,它定义了YUI构造器以及yui模块,主要包括Lang,UA,封装的Array, Object, 以及Get等等。\n2,第二层为核心工具层,主要是一些工具模块,例如DOM,Node,Event\n3,第三层为组件框架层,主要是为构建组件提供丰富灵活的机制\n4,第四层为组件层,包括了IO,JSON,Animation等重要模块\n 我们遇到很多挑战:\n1,如何将原来的功能划分为模块,如何将所有模块组织起来,这是比较大的一个挑战。\n2,Combo服务的实现。yahoo的combo只能提供YUI自身模块,而且速度在国内并不占优势。我们采用了minify,进行了一些修改和配置,能够在线上线下提供combo的支持。\n3,模块加载策略的研究。\n4,版本管理的问题。原来我们采用了query string的方式进行版本管理,现在则是用embedding的方式。\n 我们遇到很多挑战:\n1,如何将原来的功能划分为模块,如何将所有模块组织起来,这是比较大的一个挑战。\n2,Combo服务的实现。yahoo的combo只能提供YUI自身模块,而且速度在国内并不占优势。我们采用了minify,进行了一些修改和配置,能够在线上线下提供combo的支持。\n3,模块加载策略的研究。\n4,版本管理的问题。原来我们采用了query string的方式进行版本管理,现在则是用embedding的方式。\n 我们遇到很多挑战:\n1,如何将原来的功能划分为模块,如何将所有模块组织起来,这是比较大的一个挑战。\n2,Combo服务的实现。yahoo的combo只能提供YUI自身模块,而且速度在国内并不占优势。我们采用了minify,进行了一些修改和配置,能够在线上线下提供combo的支持。\n3,模块加载策略的研究。\n4,版本管理的问题。原来我们采用了query string的方式进行版本管理,现在则是用embedding的方式。\n 我们遇到很多挑战:\n1,如何将原来的功能划分为模块,如何将所有模块组织起来,这是比较大的一个挑战。\n2,Combo服务的实现。yahoo的combo只能提供YUI自身模块,而且速度在国内并不占优势。我们采用了minify,进行了一些修改和配置,能够在线上线下提供combo的支持。\n3,模块加载策略的研究。\n4,版本管理的问题。原来我们采用了query string的方式进行版本管理,现在则是用embedding的方式。\n 目前,我们已经将大多数后台系统迁移到了YUI3。本季度我们要完成主站的迁移工作。\n 在介绍迁移之前,先看一下原来我们组织js的方式。这里主要包含三类文件:\n二次开发的核心文件core.js和一些widget文件,\n应用层级的文件,例如app-deal.js,\n来自第三方的文件,例如jquery.js。\n这种方式非常简单,但在web app时代已经不再适合较为复杂的前端开发,维护成本比较高。\n 那如何划分模块呢,我们总结了如下几条原则:\n1,抽象与应用必须脱离。更通用的功能应该放在更低的层级,应用层完全面向实际问题,在解决的过程中调用抽象出来的方法。\n2,职责单一。保持每个模块的职责足够简单,方便维护和可持续开发。\n3,粒度得当。有了combo,我们可以不必担心粒度太小,文件过多导致的速度问题。但是,从可维护的角度来考虑,粒度应该适当而不宜过小,避免海底捞针的情形出现。\n4,我们的模块体系应该是开放的,不符合YUI规范的第三方模块,我们可以借鉴整合进来,使我们的基础框架更加完善,更加性感\n 那如何划分模块呢,我们总结了如下几条原则:\n1,抽象与应用必须脱离。更通用的功能应该放在更低的层级,应用层完全面向实际问题,在解决的过程中调用抽象出来的方法。\n2,职责单一。保持每个模块的职责足够简单,方便维护和可持续开发。\n3,粒度得当。有了combo,我们可以不必担心粒度太小,文件过多导致的速度问题。但是,从可维护的角度来考虑,粒度应该适当而不宜过小,避免海底捞针的情形出现。\n4,我们的模块体系应该是开放的,不符合YUI规范的第三方模块,我们可以借鉴整合进来,使我们的基础框架更加完善,更加性感\n 那如何划分模块呢,我们总结了如下几条原则:\n1,抽象与应用必须脱离。更通用的功能应该放在更低的层级,应用层完全面向实际问题,在解决的过程中调用抽象出来的方法。\n2,职责单一。保持每个模块的职责足够简单,方便维护和可持续开发。\n3,粒度得当。有了combo,我们可以不必担心粒度太小,文件过多导致的速度问题。但是,从可维护的角度来考虑,粒度应该适当而不宜过小,避免海底捞针的情形出现。\n4,我们的模块体系应该是开放的,不符合YUI规范的第三方模块,我们可以借鉴整合进来,使我们的基础框架更加完善,更加性感\n 那如何划分模块呢,我们总结了如下几条原则:\n1,抽象与应用必须脱离。更通用的功能应该放在更低的层级,应用层完全面向实际问题,在解决的过程中调用抽象出来的方法。\n2,职责单一。保持每个模块的职责足够简单,方便维护和可持续开发。\n3,粒度得当。有了combo,我们可以不必担心粒度太小,文件过多导致的速度问题。但是,从可维护的角度来考虑,粒度应该适当而不宜过小,避免海底捞针的情形出现。\n4,我们的模块体系应该是开放的,不符合YUI规范的第三方模块,我们可以借鉴整合进来,使我们的基础框架更加完善,更加性感\n 美团的Js架构,按照抽象与应用程度,分为四层。1,最底层交给强悍的YUI3,为我们提供很跨浏览器的api和很好的框架。2,第二层是我们二次开发的一些核心方法和控件库。mt-base中包含strtotime,getRadioValue等基础方法,对Cookie的简单操作,一些封装的页面动画等。w-base,w-autocomplete等包含一些封装的控件,提供更加高效的用户体验,且便于后端人员调用。3,第三层包含美团各个分站点的一些通用模块。例如mis-base包含后台mis系统的消息系统、checkFormChanged等通用方法。这一层更加接近应用。4,最上面一层,应用模块,这些模块的方法都是用来解决实际问题的。例如mis-deal用来处理mis系统中所有deal相关页面的交互,finance-pay用来处理财务系统中的付款相关页面的交互。一些零碎的应用方法我们放在对应站点的misc模块中。\n 美团的Js架构,按照抽象与应用程度,分为四层。1,最底层交给强悍的YUI3,为我们提供很跨浏览器的api和很好的框架。2,第二层是我们二次开发的一些核心方法和控件库。mt-base中包含strtotime,getRadioValue等基础方法,对Cookie的简单操作,一些封装的页面动画等。w-base,w-autocomplete等包含一些封装的控件,提供更加高效的用户体验,且便于后端人员调用。3,第三层包含美团各个分站点的一些通用模块。例如mis-base包含后台mis系统的消息系统、checkFormChanged等通用方法。这一层更加接近应用。4,最上面一层,应用模块,这些模块的方法都是用来解决实际问题的。例如mis-deal用来处理mis系统中所有deal相关页面的交互,finance-pay用来处理财务系统中的付款相关页面的交互。一些零碎的应用方法我们放在对应站点的misc模块中。\n 美团的Js架构,按照抽象与应用程度,分为四层。1,最底层交给强悍的YUI3,为我们提供很跨浏览器的api和很好的框架。2,第二层是我们二次开发的一些核心方法和控件库。mt-base中包含strtotime,getRadioValue等基础方法,对Cookie的简单操作,一些封装的页面动画等。w-base,w-autocomplete等包含一些封装的控件,提供更加高效的用户体验,且便于后端人员调用。3,第三层包含美团各个分站点的一些通用模块。例如mis-base包含后台mis系统的消息系统、checkFormChanged等通用方法。这一层更加接近应用。4,最上面一层,应用模块,这些模块的方法都是用来解决实际问题的。例如mis-deal用来处理mis系统中所有deal相关页面的交互,finance-pay用来处理财务系统中的付款相关页面的交互。一些零碎的应用方法我们放在对应站点的misc模块中。\n 美团的Js架构,按照抽象与应用程度,分为四层。1,最底层交给强悍的YUI3,为我们提供很跨浏览器的api和很好的框架。2,第二层是我们二次开发的一些核心方法和控件库。mt-base中包含strtotime,getRadioValue等基础方法,对Cookie的简单操作,一些封装的页面动画等。w-base,w-autocomplete等包含一些封装的控件,提供更加高效的用户体验,且便于后端人员调用。3,第三层包含美团各个分站点的一些通用模块。例如mis-base包含后台mis系统的消息系统、checkFormChanged等通用方法。这一层更加接近应用。4,最上面一层,应用模块,这些模块的方法都是用来解决实际问题的。例如mis-deal用来处理mis系统中所有deal相关页面的交互,finance-pay用来处理财务系统中的付款相关页面的交互。一些零碎的应用方法我们放在对应站点的misc模块中。\n \n \n \n \n \n \n \n \n \n \n \n \n \n 为了保持向前兼容,我们定义了新的全局对象M。我们对YUI进行了简单的封装,可以使用M.add添加模块,使用M.use调用模块。请注意,每次使用M.use都会新生成一个config的实例,这个config信息主要包含一些combo服务器信息,我们自己开发模块的信息。这样loader就知道该如何计算依赖的模块了。\n在对use的封装中,我们还引入了debug的功能。[代码演示]\n [代码演示]\n 演示页脚的依赖信息M.Groups\n \n 目前我们采用的加载方式是:预加载通用基础模块,例如yui,node,event,io等,然后是站点级别的一些操作,例如mis系统的widget初始化、消息系统初始化等,最后是页面级别的一个特定应用入口。\n 目前我们采用的加载方式是:预加载通用基础模块,例如yui,node,event,io等,然后是站点级别的一些操作,例如mis系统的widget初始化、消息系统初始化等,最后是页面级别的一个特定应用入口。\n 目前我们采用的加载方式是:预加载通用基础模块,例如yui,node,event,io等,然后是站点级别的一些操作,例如mis系统的widget初始化、消息系统初始化等,最后是页面级别的一个特定应用入口。\n 我们对基于PHP loader的服务器端loader进行了尝试,并准备近期进行部署。\n服务器端loader优势在于速度,同时,将其整合在框架中降低了维护成本,简便易用。\n 通过使用服务器端loader,可以做到一次性加载。\n 发布脚本会把文件的md5保持在FileHelper中\n \n \n \n