模块规范

layui 的模块是基于 layui.js 内部实现的异步模块加载方式,它并不遵循于AMD(没有为什么,毕竟任性呀!),而是自己定义了一套更轻量的模块规范。并且这种方式在经过了大量的实践后,成为 layui 最核心的模块加载引擎。

预先加载

开门见山,还是直接说使用比较妥当。Layui的模块加载采用核心的 layui.use(mods, callback)方法,当你的JS 需要用到Layui模块的时候,我们更推荐你采用预先加载,因为这样可以避免到处写layui.use的麻烦。你应该在最外层如此定义:

  1. /*
  2. Demo1.js
  3. 使用Layui的form和upload模块
  4. */
  5. layui.use(['form', 'upload'], function(){ //如果只加载一个模块,可以不填数组。如:layui.use('form')
  6. var form = layui.form //获取form模块
  7. ,upload = layui.upload; //获取upload模块
  8.  
  9. //监听提交按钮
  10. form.on('submit(test)', function(data){
  11. console.log(data);
  12. });
  13.  
  14. //实例化一个上传控件
  15. upload({
  16. url: '上传接口url'
  17. ,success: function(data){
  18. console.log(data);
  19. }
  20. })
  21. });

按需加载(不推荐)

如果你有强迫症,你对网站的性能有极致的要求,你并不想预先加载所需要的模块,而是在触发一个动作的时候,才去加载模块,那么,这是允许的。你不用在你的JS最外层去包裹一个大大的 layui.use,你只需要:

  1. /*
  2. Demo2.js
  3. 按需加载一个Layui模块
  4. */
  5.  
  6. //……
  7. //你的各种JS代码什么的
  8. //……
  9.  
  10. //下面是在一个事件回调里去加载一个Layui模块
  11. button.addEventListener('click', function(){
  12. layui.use('laytpl', function(laytpl){ //温馨提示:多次调用use并不会重复加载laytpl.js,Layui内部有做模块cache处理。
  13. var html = laytpl('').render({});
  14. console.log(html);
  15. });
  16. });

注意:如果你的 JS 中需要大量用到模块,我们并不推荐你采用这种加载方式,因为这意味着你要写很多 layui.use(),代码可维护性不高。
建议还是采用:预先加载。即一个JS文件中,写一个use即可。

模块命名空间

layui 的模块接口会绑定在 layui 对象下,内部由 layui.define() 方法来完成。每一个模块都会一个特有的名字,并且无法被占用。所以你无需担心模块的空间被污染,除非你主动 delete layui.{模块名}。调用模块可通过 layui.use 方法来实现,然后再通过 layui 对象获得模块接口。如:

  1. layui.use(['layer', 'laypage', 'laydate'], function(){
  2. var layer = layui.layer //获得layer模块
  3. ,laypage = layui.laypage //获得laypage模块
  4. ,laydate = layui.laydate; //获得laydate模块
  5.  
  6. //使用模块
  7. });

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

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

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

事实上,如果你不想采用 layui.use,你可以引入 layui.all.js 来替代 layui.js,见:全模块用法

扩展一个 layui 模块

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

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

第二步:编写test.js 如下:

  1. /**
  2. 扩展一个test模块
  3. **/
  4.  
  5. layui.define(function(exports){ //提示:模块也可以依赖其它模块,如:layui.define('layer', callback);
  6. var obj = {
  7. hello: function(str){
  8. alert('Hello '+ (str||'mymod'));
  9. }
  10. };
  11.  
  12. //输出test接口
  13. exports('mymod', obj);
  14. });

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

  1. //config的设置是全局的
  2. layui.config({
  3. base: '/res/js/' //假设这是你存放拓展模块的根目录
  4. }).extend({ //设定模块别名
  5. mymod: 'mymod' //如果 mymod.js 是在根目录,也可以不用设定别名
  6. ,mod1: 'admin/mod1' //相对于上述 base 目录的子目录
  7. });
  8.  
  9. //你也可以忽略 base 设定的根目录,直接在 extend 指定路径(主要:该功能为 layui 2.2.0 新增)
  10. layui.extend({
  11. mod2: '{/}http://cdn.xxx.com/lib/mod2' // {/}的意思即代表采用自有路径,即不跟随 base 路径
  12. })
  13.  
  14. //使用拓展模块
  15. layui.use(['mymod', 'mod1'], function(){
  16. var mymod = layui.mymod
  17. ,mod1 = layui.mod1
  18. ,mod2 = layui.mod2;
  19.  
  20. mymod.hello('World!'); //弹出 Hello World!
  21. });

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

结语

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

layui - 用心与你沟通