javascript模块研究之 - CMD模式 seajs使用

前言 - 什么是 CMD 模式

CMD是 Common Module Definition 的缩写,意思就是通用模块加载规范

CMD 模式的 需要载入 Sea.js 这个包, 浏览器兼容ie5.5+ 所以放心用吧。

下载地址 http://seajs.org/

模块定义方式:

define("ID",["依赖模块"],function (require, exports, module) {

});

ID 当前模块的唯一
["..."] 依赖模块
require 用来载入其它模块
exports 导出方法
module 导出模块

简单模块调用

  • 定义一个模块 module1.js
// 单例模式
define(function(require, exports, module) {

    console.log("module1 被装载~");

    exports.num = 10;

    exports.add = function(){
        this.num ++;
    };

    exports.get = function(){
        return this.num;
    };

});

通过 exports 导出了2个方法 add get,一个属性 num。
方法中访问成员变量 this.num 方式。

  • 建立调用页面 1-seajs模块调用.html
<script src="../sea-modules/core/sea.js" id="seajsnode" ></script>
<script>
    seajs.config({
        base: "../sea-modules/",
    });

    seajs.use(['lib/module1'],function(mod1){
        mod1.add();
        mod1.add();
        console.log(mod1.get());
    });

    seajs.use(['lib/module1'],function(mod1){
        mod1.add();
        mod1.add();
        console.log(mod1.get());
    });
</script>

导入sea.js包
定义seajs.config 的 base 代码根目录
seajs.use方式 使用 module1
连续调用了两次

  • 输出

module1 被装载~
12
14

我们可以发现这是单例模式,作用域是整个页面,所以num是累加了。

非单例模式

  • 定义模块
// 非单例模式
define(function(require, exports, module) {

    console.log("module2 被装载~");

    function UserModel() {

        var num = 1000;
        var name = "AAAAA";
        var uid = "1001";

        this.add = function () {
            num ++;
        };
        this.show = function () {
            return num + ":" + name + ":" + uid;
        };
    }

    module.exports = function () {
        return new UserModel();
    };
});

模型方式导出 module.exports

  • 定义入口 2-seajs非单例模块.html
<script src="../sea-modules/core/sea.js" id="seajsnode" ></script>
<script>
    seajs.config({
        base: "../sea-modules/",
    });

    seajs.use(['lib/module2'],function(mod2){

        var mod = new mod2();
        mod.add();
        mod.add();
        mod.add();

        console.log(mod.show());
    });

    seajs.use(['lib/module2'],function(mod2){

        var mod = new mod2();
        mod.add();
        mod.add();
        mod.add();

        console.log(mod.show());
    });
</script>

seajs.use 调用后 是一个 function()
我们用 new 的方式实例一个新对象
这里也是重复调用两次

  • 输出

module2 被装载~
1003:AAAAA:1001
1003:AAAAA:1001

可以发现这次是非单例了,每次都是新的对象,互不影响。

模块依赖

  • 定义模块
// 模块依赖
define(['module1'],function(require, exports, module) {

    console.log("module3 被装载~");

    var mod1 = require('module1');
    mod1.add();

    console.log("module1 执行完成");
});

依赖模块 module1
require装载 module1 ,并执行 add 操作

  • 定义入口 3-seajs模块依赖.html
<script src="../sea-modules/core/sea.js" id="seajsnode" ></script>
<script>
    seajs.config({
        base: "../sea-modules/",
        alias: {
            "module1": "lib/module1.js"
        }
    });

    seajs.use(['lib/module3'],function(mod3){

        console.log("module3 执行完成");
    });
</script>

seajs.config alias 设置别名 module1

  • 输出

module3 被装载~
module1 被装载~
module1 执行完成
module3 执行完成

可以发现 CMD 果然是顺序执行,模块是懒加载,在需要的时候加载,不会像AMD方式先加载模块。
下载操作,是在执行定义依赖 define(['module1'],... 时浏览器客户端开始下载。

异步方式加载

define(function(require) {

  require.async('module1', function(mod1) {
    mod1.add();
  });

});

require.async 异步加载一个模块,在加载完成时,执行回调

模块化第三方代码 jquery

规范了模块的定义虽然好,但是用第三非CMD定义模块时,就有点麻烦了,比如这个jquery,你直接 require 直接返回 null

  • 修改jquery的代码
define(function () {

    // jquery代码
    ...
    
    // 加入return
    return $.noConflict();
});

用一个 define 包裹下
最后 return $.noConflict();

  • 定义模块
define("lib/module4", ["./module4-ui"], function(require) {
    var ui = require("./module4-ui");
    ui.setup();
});

define("lib/module4-ui", ["jquery"], function(require, exports, module) {

    var $ = require("jquery");

    exports.setup = function () {

        $("#myButton").click( function () {
            alert(123);
        });
    };
});

我把UI处理单独出来了,设置模块ID define("lib/module4"
var $ = require("jquery"); 方式载入jquery模块 测试一个按钮事件

  • 定义入口
<script src="../sea-modules/core/sea.js" ></script>

<script>
    seajs.config({
        base: "../sea-modules/",
        alias: {
            "jquery": "core/jquery-3.1.1.seajs.min.js"
        }
    });

    seajs.use("lib/module4");
</script>

<button id="myButton">点击我</button>

alias配置了别名 模块中可以直接使用
放置了一个按钮button

  • 输出
seajs-jquery-cmd化

触发成功

模块化 调用jquery插件

同样你要用相关依赖jquery的插件,也需要修改相关代码。

我这里修改了一个确认对话框插件 artDialog

  • 修改插件主程序 dialog.js
define("lib/artDialog/dialog", ["jquery"], function (require, exports, module) {

    var jQuery = require("jquery");

    // 放置原来的插件代码

    module.exports = function (options, ok, cancel) {
        return new dialog(options, ok, cancel);
    };
});

首先包一个 define 定义
然后创建依赖需要的 var jQuery = require("jquery"); 对象
最后导出定义模块定义 module.exports = function ...

  • 修改上面的模块代码
define("lib/module4", ["./module4-ui"], function(require) {
    var ui = require("./module4-ui");
    ui.setup();
});

define("lib/module4-ui", ["jquery","dialog"], function(require, exports, module) {

    var $ = require("jquery");
    var dialog = require("dialog");

    exports.setup = function () {

        $("#myButton").click( function () {
 
            var d = dialog({
                title: '欢迎',
                content: '欢迎使用 artDialog 对话框组件!'
            });
            d.showModal();
        });
    };
});

读取调用 var dialog = require("dialog");

  • 修改上面的入口
<script src="../sea-modules/core/sea.js" ></script>
<script src="../sea-modules/core/seajs-css.js" ></script>

<script>
    seajs.config({
        base: "../sea-modules/",
        alias: {
            "jquery": "core/jquery-3.1.1.seajs.min.js",
            "dialog": "lib/artDialog/dialog.js"
        }
    });

    seajs.use("lib/artDialog/ui-dialog.css");
    seajs.use("lib/module4");


</script>

<button id="myButton">点击我</button>

加入alias别名 dialog
这里用了一个 seajs-css 的插件动态读取了css
插件地址 https://github.com/seajs/seajs-css/blob/master/README.md

  • 输出
seajs-jquery-cmd化-插件

弹出成功!

参考代码

https://github.com/hans007/JavaScriptCodes/tree/master/seajs%E6%A8%A1%E5%9D%97%E5%8C%96/app

我的博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,165评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,503评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,295评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,589评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,439评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,342评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,749评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,397评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,700评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,740评论 2 313
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,523评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,364评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,755评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,024评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,297评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,721评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,918评论 2 336

推荐阅读更多精彩内容