- 预先加载模块
- 模块命名空间
- 扩展一个 layui 模块

-

# 模块规范

> layui 定义了一套更轻量的模块规范。并且这种方式在经过了大量的实践后，成为 layui 最核心的模块加载引擎。

预先加载模块

layui 通过 use 方法加载模块。当你的 JS 需要用到 layui 模块的时候，且避免到处写 layui.use() 的麻烦。你应该在最外层如此定义：

    layui.use(['form', 'upload'], function(){  //如果只加载一个模块，可以不填数组。如：layui.use('form')
      var form = layui.form //获取form模块
      ,upload = layui.upload; //获取upload模块

      //监听提交按钮
      form.on('submit(test)', function(data){
        console.log(data);
      });

      //实例化一个上传控件
      upload({
        url: '上传接口url'
        ,success: function(data){
          console.log(data);
        }
      })
    });

模块命名空间

layui 的模块对象会绑定在 layui 对象下，内部由 layui.define() 方法来完成。每个模块都有一个特定命名，且无法被占用。所以你无需担心模块的空间被污染，除非你主动 delete layui['模块名']。调用模块可通过 layui.use() 来实现，再通过 layui 对象获得模块对象。如：

    layui.use(['layer', 'laypage', 'laydate'], function(){
      var layer = layui.layer //获得 layer 模块
      ,laypage = layui.laypage //获得 laypage 模块
      ,laydate = layui.laydate; //获得 laydate 模块

      //使用模块
    });

我们推荐你将所有的业务代码都写在一个大的 use 回调中，而不是将模块接口暴露给全局，比如下面的方式我们是极不推荐的：

    //强烈不推荐下面的做法
    var laypage, laydate;
    layui.use(['laypage', 'laydate'], function(){
      laypage = layui.laypage;
      laydate = layui.laydate;
    });

你之所以想使用上面的错误方式，是想其它地方使用不在执行一次 layui.use？但这种理解本身是存在问题的。因为如果一旦你的业务代码是在模块加载完毕之前执行，你的全局对象将获取不到模块接口，因此这样用不仅不符合规范，还存在报错风险。建议在你的 js 文件中，在最外层写一个 layui.use 来加载所依赖的模块，并将业务代码写在回调中，这样还可以确保 html 文档加载完毕再执行回调代码。

扩展一个 layui 模块

layui 官方提供的模块有时可能还无法满足你，或者你试图按照layer的模块规范来扩展一个模块。那么你有必要认识layui.define()方法，相信你在文档左侧的“底层方法”中已有所阅读。下面就让我们一起扩展一个 layui 模块吧：

第一步：确认模块名，假设为：mymod，然后新建一个mymod.js 文件放入项目任意目录下（注意：不用放入layui目录）

第二步：编写 mymod.js 如下：

    /**
      扩展一个 mymod 模块
    **/

    layui.define(function(exports){ //提示：模块也可以依赖其它模块，如：layui.define('mod1', callback);
      var obj = {
        hello: function(str){
          alert('Hello '+ (str||'mymod'));
        }
      };

      //输出 mymod 接口
      exports('mymod', obj);
    });

第三步：设定扩展模块所在的目录，然后就可以在别的JS文件中使用了

    //config的设置是全局的
    layui.config({
      base: '/res/js/' //假设这是你存放拓展模块的根目录
    }).extend({ //设定模块别名
      mymod: 'mymod' //如果 mymod.js 是在根目录，也可以不用设定别名
      ,mod1: 'admin/mod1' //相对于上述 base 目录的子目录
    });

    //你也可以忽略 base 设定的根目录，直接在 extend 指定路径（主要：该功能为 layui 2.2.0 新增）
    layui.extend({
      mod2: '{/}http://cdn.xxx.com/lib/mod2' // {/}的意思即代表采用自有路径，即不跟随 base 路径
    })

    //使用拓展模块
    layui.use(['mymod', 'mod1'], function(){
      var mymod = layui.mymod
      ,mod1 = layui.mod1
      ,mod2 = layui.mod2;

      mymod.hello('World!'); //弹出 Hello World!
    });

大体上来说，layui 的模块定义很类似 Require.js 和 Sea.js，但跟他们又有着明显的不同，譬如在接口输出等地方。

结语

其实关于模块的核心，就是 layui.js 的两个底层方法：一个用于定义模块的 layui.define()，一个加载模块的 layui.use()。

layui - 在每一个细节中，用心与你沟通