YUI3: Creating Your Own Modules

本文节选翻译自YUI3 Cookbook,翻译的目的是force自己focus看完,因为最近实在过于焦躁不安心神不宁;好了废话不多说,我们开始,因为可能牵涉到版权问题,所以恕不能同时附上英文原文。水平有限,如有错误皆是本人认知问题,与原文无关。

[问题]
你需要以YUI模块的形式来包装并复用你的code。

[解决办法]
使用YUI.add()方法把你的code注册成为YUI全局对象(YUI global object)的一个模块。最少需要给YUI.add()提供:

  • 一个模块的名字。习惯上,YUI模块的名字一般为小写字母,使用hyphens(-)分割;
  • 一个实际定义模块代码的回调函数(callback function)。可以通过把这个component定义到Y对象上的方法来expose这个模块的相关属性或方法。

一旦YUI.add()执行完毕,你便可以像其它任何YUI模块一样来使用你自己的代码。下面的例子里面i,模块定义之后紧接着的就是YUI().use(),它会加载模块以及其依赖,并在回调函数里面执行其模块方法。

<!DOCTYPE html>
<title>Creating and using a Hello World module</title>
<div id="demo"></div>
<script type="text/javascript" src="http://yui.yahooapis.com/3.8.0/build/yui/yui-min.js"></script><script type="text/javascript">
  YUI.add('hello', function (Y) {
    Y.namespace('Hello');
    Y.Hello.sayHello = function () {
      return 'GREETINGS PROGRAMS';
    };
  });
  YUI().use('node-base', 'hello', function (Y) {
    Y.one('#demo').setHTML(Y.Hello.sayHello());
  });
</script>

为了避免命名冲突,你可以使用Y.namespace()来创造一个“Hello”的namespace作为这个sayHello()方法的命名空间。Y.namespace()是个方便实用的工具,虽然这里例出的例子非常简单,本质上等同于:

Y.Hello = {};
注:上面这个例子只展现出最基本的创建模块的代码block。这个example对于构建真正可复用的code并不足够。真实世界里面的模块需要定义依赖和其它metadata,且它们通常会被定义在另外独立的文件中。


[讨论]
正如介绍和Recipe 1.1里面提到的,YUI分离了模块定义注册和模块执行。YUI.add()在YUI全局对象(YUI global object)上注册模块,YUI().use()则是把该模块附到一个Y实例上,从而让你可以执行模块定义的函数和方法。YUI.add()和YUI().use()被设计成协同合作;首先你注册你的code,然后晚些时候你取回并执行它。

当设计应用程序时,一直思考怎样才能尽可能的把最多的code移出use()方法而移到add()方法里面。在add()里面的回调函数是可复用的,在use()里面的回调函数则是不可复用的,它们应该是一些胶水代码(glue code)被用来把一个application code应用到某个特定的页面。

如果你仔细比较YUI().use()和YUI.add(),你可能会注意到YUI.add()方法里面少了一对括号。这是一个重要的不同:

  • YUI.add()是个静态方法(static method),它注册模块code到YUI全局对象(YUI global object)上
  • YUI().use()是个工厂方法(factory method),它用相关的config来创建YUI实例

YUI全局对象存储着一堆可用的常用code。Y对象里面则hold着特定的代码子集,这些代码是你想要在YUI.add()里面注册的或是在YUI().use()里面使用的。另外,命名成Y则是一个strong的习惯约定。在一个沙盒(sandbox)里面,你可以把这个YUI实例命名成任何名字,不过通常你应该只在嵌套的使用use() sandbox的时候修改此约定命名,否则你需要告诉其它的开发人员这个instance的命名相对奇怪。

YUI.add()的核心则是那个定义模块代码的回调函数。所有被附在Y实例上的函数或对象会在之后的use()回调函数里面可用。所有未被附在Y实例上的东西都保持私有(private)。

当需要附加函数和对象的时候,考虑使用namespace隔离命名空间而不是直接附到Y上,因为这块空间被用来预留给少数的YUI核心方法。你可以通过创建空对象来手动创建namespace,或是调用Y.namespace()实用方法。Y.namespace()接受一个或多个字符串并在该Y对象上创建相对应的namespace。已经存在的namespace并不会被覆盖。在需要一下子创建多个namespace或者像Y.Example.Hello这样的嵌套namespace的时候,Y.namespace()会非常方便。Y.namespace()还会返回最后一个指定的namespace,所以需要的话还可以inline的使用它:

Y.namespace('Hello').sayHello = function () { ...

你可能会好奇YUI的核心模块是不是也是用YUI.add()?实际上,所有的YUI核心模块全部在构建时被包装到一个YUI.add()方法里面,这些都归功于YUI构建工具(YUI Builder tool)。如果你下载并解压YUI SDK,你会在/src文件夹下找到原始未被包装的源代码文件,被包装过的模块文件则在/build文件夹下面。换言之,这里没有任何magic,所有YUI的核心模块其实也都是使用和我们自定义模块使用的相同接口来注册它们自己。

[相关]
使用YUI Builder的相关instructions。

[Footnotes]
  1. 译者改成了使用yui3最新版:3.8.0 []

历史上的今天:

Related posts:

Trackbacks for this post

  1. YUI3: Creating a Module with Dependencies | Samson's Weblog United States WordPress Unknow Os

Got something to say? Go for it!

使用新浪微博登陆