3-CMD

诞生背景
AMD其实已经算是解决了前端模块化开发的问题了,但是!!!但是,因为AMD管理依赖的时候,会把所有的依赖下载到本地,并且立即执行一次。依赖少了还好,多的话,那么多js均要被执行一次,这个内存消耗就不容小觑了。而且最重要的是,执行js会阻塞dom的渲染。用户的直接感觉就是页面初始加载的时候等待的时间较长。然后china有一个叫‘玉伯’的牛人,开发了个类库sea.js。seaJs核心即AMD模块化开发规范

 

 

核心规范
CMD(Common Module Definition)更贴近 CommonJS Modules/1.1 和 Node Modules 规范,一个模块就是一个文件;
它推崇 依赖就近 想什么时候 require 就什么时候加载,实现了 懒加载, 延迟执行 (as lazy as possible) ;
经常使用的 API 只有 define, require, require.async, exports, module.exports 这五个。其他 API 有个印象就好。
特性:=====预先下载,延迟执行===
会提前下载好所有requre后的文件,但是并不执行模块内容,直到需要执行的时候才执行

 

实例代码
index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div class="wrapp">
        <input type="text"></br>
        <input type="text"></br>
        <button>求和</button></br>
        <div class="sumWrap"></div>
    </div>
    <script src="lib/jquery-3.2.1.min.js"></script>
    <script src="lib/sea.js"></script>
    <script src="js/app.js"></script>
</body>
</html>

 

app.js

/**
 *模块:
 *功能:入口
 */
seajs.use(['./js/tools'],function (tools) {
    $('button').click(function () {
        var num1=$('input:eq(0)').val();
        var num2=$('input:eq(1)').val();
        var sum=tools.add(num1,num2);
        $('.sumWrap').text(sum)
    })
});

 

tools.js

/**
 *模块:tools
 *功能:工具
 */
define(function (require, exports, module) {
    return {
        add:function (x,y) {
            var sum= Number(x)+Number(y);
            var log=require('./log');
            log.info('tools>add执行结果为:'+sum);
            return sum;
        }
    }
})

 

 

log.js

/**
 *模块:log模块
 *功能:打印
 */
console.log('cmd log.js文件--我被下载啦')
define(function () {
    console.log('cmd log模块--我被执行啦')
    return {
        info:function (str) {
            console.log(str)
        },
        err:function (str) {
            console.error(str)
        }
    }
})

 

 

效果

看到没有,cmd会提前把所有的依赖下载到本地资源中,但是并不执行(也叫加载),直到遇到require的时候,才执行。

比如说那个log.js刷新页面看浏览器的network或者source都已经有该文件了,也就是说项目初始化的时候就下载了该模块(即该模块所在的文件,因为cmd推崇一个模块就是一个文件),为测试,我打印了‘log.js被下载啦’
但是log模块并没有执行,点击计算求和的时候,在tools的add方法里有require('log.js'),这个时候,log.js里定义的模块才被加载执行
这就叫做‘依赖后置,使用时才加载(懒加载、 延迟执行)’

这就很好的解决了初始化AMD那样会下载并执行完所有的模块引起的卡屏问题

不过默认下require是同步的,也就是说,require的模块没有执行完,程序是不会继续往下执行的。这样就很类似于nodeJs的commomJS模块开发规范了。
当然如果有些人觉得这样虽然很干净利索,但是还是没有会掉性能优化,那么CMD提供了异步的方案

require.async('[模块a]', function(a) {
    a.doSomething();
});


但是我觉得,这样这样写太矫情了,就好比你一直吃红薯(写回调),突然吃大米(像传统高级语言那样简单的写同步)很不习惯!!!

 

作者总结
由于目前浏览器尚不支持模块化CMD规范,所以这些关键字无法被识别,需要先引入库sea.js

补充一点
与AMD不同的小细节,CMD追求与node写法一样,所以也为我们提供了moudule.export,它其实等价于return 关键字,就是大家所说的语法糖。所以tools.js和log.js我可以改成如下这样,效果不变
tools.js

/**
 *模块:tools
 *功能:工具
 */
define(function (require, exports, module) {
    var add=function (x,y) {
        var sum= Number(x)+Number(y);
        var log=require('./log');
        log.info('tools>add执行结果为:'+sum);
        return sum;
    }

    //等价于return
    module.exports = {
        add: add
    };
})

 

log.js

/**
 *模块:log模块
 *功能:打印
 */
console.log('cmd log.js文件--我被下载啦')
define(function (require, exports, module) {
    console.log('cmd log模块--我被执行啦')
    var info=function (str) {
        console.log(str)
    };
    var err=function (str) {
        console.error(str)
    };
    //等价于return
    module.exports = {
        info: info,
        err: err
    };
})

 

posted @ 2018-01-29 15:54  丁少华  阅读(278)  评论(0编辑  收藏  举报