模块文件模板
这里是一段最常用的模块定义的代码:
/*jslint devel: true, undef: true, newcap: true, strict: true, maxerr: 50 */ /*global YUI*/ /** * The module-name module creates the blah blah * @module module-name */ YUI.add(‘module-name’, function (Y) { "use strict"; // handy constants and shortcuts used in the module var Lang = Y.Lang, CBX = ‘contentBox’, BBX = ‘boundingBox’, NAME = ‘xxxx’;
/** * The Xxxx class does …. * @class Xxxx * @extends Widget * @uses WidgetParent * @constructor * @cfg {object} configuration attributes */ Y.Xxxx = Y.Base.create( NAME, Y.Widget, [Y.WidgetParent], { // Instance members here }, { // Static members here, specially: ATTRS: { } } );
}, ’0.99′, { requires: ['widget','widget-parent'], skinnable: true });
前两行是供JSLint过滤这段代码用的,JSLint是我非常推荐的一个javascript语法检查工具。在JSLint网页版本中,会有一个选项区来设置选项,这排checkbox在页面的底部,如果你使用YUI Builder,JSLint会自动去读取注释中的配置,来依此对你的代码进行语法检查。
接下来的注释是为了生成YUIDoc,这会为你省去不少麻烦,文档有固定格式的模板,你只要通过注释语法填充内容就可以了。当项目越来越大,你就会越来越依赖这种项目文档。
现在开始真正的代码段,YUI.add()语句。我们用YUI.add()来告知Loader模块名称、模块内容、以及其他的一些信息。模块名通常使用小写字母加中横线组成,这些模块名称就是你在YUIAPI文档左侧看到的名字列表。当然你也看到有很多不是小写字母加中横线的命名,毕竟这种命名方法并非强制,你可以根据你的习惯做模块命名。
YUI.add()的第二个参数是一个带入YUI实例的函数,这个实例通常被命名为Y,这个回调中的逻辑即是模块的主体部分,而你需要依赖的模块的功能方法都会被挂载到这个Y上。跳到代码的结尾,你会看到YUI.add()剩下的参数,版本号(也可以不需要)和模块配置项,模块配置项是一个对象,这里代码的含义就是告诉Loader这个模块依赖了widget和widget-parent,并包含皮肤。当然,在这个例子中widget是多余的,因为widget-parent依赖了widget,这时即便你写上widget,Loader也不会重复加载widget。而且你根本不必在意模块的顺序,Loader会计算他们的依赖关系并做好排序。你也会注意到YUI APIdoc中Loader包含一个addModule()方法,YUI.add的功能就和它很类似。
在函数体内,首先是“use strict”的声明,这个声明源自ECMAScript5,这使你的代码对于未来的解释器也具备足够好的适应能力,对于旧的解释器也只相当于定义了一个孤零零的字符串值而已,不妨碍程序运行。“use”声明指定了一个函数作用域,因此将这句声明放在YUI.add()内比放在文件最顶部要更安全一些,因为如果将其放在全局,这回影响后续加载的所有JS逻辑。
然后是定义常量和变量的缩写,JavaScript本身没有常量的概念,这里的“常量”只是一种约定,和在其他编程语言中一样,常量通常使用大写字母和下划线来命名。这样做的好处有两个,特别是字符串常量,一是当你多次写一个字符串的时候,如果字符串拼错则只能在运行时报错,当改为常量形式如果出错在JSLint语法检查时就能发现。二是让YUICompressor工作效率更高,使用常量可以节省不少字节数。通常,我们更多的把配置属性和事件名称定义为常量。
缩写,比如用Lang代替Y.Lang,写的更少,解释器执行更快(直接使用引用而不是逐级查找对象成员)。
在API docs所需的文档注释后是实际的代码,我们需要将自己的模块对象挂载在Y上, 比如 Y.Xxxx。我建议采用Y.Base.create()来创建模块,这样能创建Base的派生类(Widget即派生自Base),Base模板基本能满足大多数的模块功能需求,因此不必在用其他方式来代替Y.Base.create。其中的第一个参数是模块名称,NAME属性是Base的一个描述,通常用驼峰命名法,这个名字会用于事件的前缀(例如”io:success”),抑或是组件容器的class命名前缀(例如:”yui3-xxxx-content”),此外,NAME还是执行“实例.toString()”时的默认返回值,在debugger模式下经常看到很多类似的log。这里我们使用常量NAME来标示类模块的名称。
create()的第二个参数是要派生的父类。比如,你会使用Y.Base作为无UI组件的父类、使用Y.Widget作为带UI组件的父类、Y.Plugin.Base作为插件的父类、或者使用任意派生自Y.Base的子类作为父类,也就是说,任意通过Y.Base.create()创建的类都可以再次通过create()被继承。
第三个参数是一个参元类,摻元类的方法都将挂载到你的类上,常用的参元类包括从Base派生来的ArrayList、从Widget.Attribute派生来的类似Widget-Xxxx的子模块、EventTarget和PluginHost(这两个参元类已经被Base继承),YUI中的继承机制是如此强大,以至于你看Overlay的源码仅仅是一句从Widget的继承。子类可以继承自多个父类,因此第三个参数是一个数组。
最后是实际的代码实现部分。第四个和第五个参数都是对象,它们包含了实例,和类中的静态成员。实例属性通过深拷贝挂载到类的原型(prototy)上,通过this来访问他们,其他静态成员则是可公开访问的。
出处:Taobao.com UED Team
责任编辑:bluehearts
上一页 使用YUI 3开发Web应用的诀窍 [1] 下一页 使用YUI 3开发Web应用的诀窍 [3]
◎进入论坛网页制作、WEB标准化版块参加讨论,我还想发表评论。
|