javascript设计模式——AMD模式学习

模块化:将复杂的系统分解为高内聚、低耦合的模块,使系统开发变得可控、可维护、可拓展,提高模块的复用率。
异步模块——AMD:请求发出后,继续其他业务逻辑,知道模块加载完城执行后续的逻辑,实现模块开发中对模块加载完成后的引用。
优点有很多,比如:
1:懒加载,提高网站性能
2:功能模块化
3:解决命名冲突
4:...
参考require.js,那么我们来实现一个简单的amd库,主要有三个模块方法
1.config——配置模块路径
2.define——定义模块方法
3.require——模块入口方法
以下是实现学习版的基本函数

;
(function(win) {
    win.config = {}; //路径配置
    var cache = {}, //模块缓存
        require = function(deps, callback) {//模块入口方法,deps,依赖模块
            count = 0, //未加载的模块计数器
        },
        define = function(url, callback) {}, //定义模块方法
        loadModule = function(url, callback) {}, //模块加载方法
        loadDone = function(params, callback){},//所有模块加载完毕
        loadSript = function(url) {}; //加载js文件
    win.require = require;
    win.define = define;
})(window);

  同时我们新建三个js文件,皆为同一个路径,分别为demo.js,demo1.js,demo2.js

//demo1.js文件内容
define('demo1',function(){
    return {
        a: 1
    }
})
//demo2.js文件内容
define('demo2',function(){
    return {
        b: 2
    }
})
//demo.js
window.config = {
    demo1: './demo1.js',
    demo2: './demo2.js'
}
require(['demo1', 'demo2'], function(demo1, demo2) {
    console.log(demo1)
    console.log(demo2)
})

  上面看起来很像是require.js的写法吧!想必看了上面的代码就知道这个代码的意思,现在来让我们实现它吧!

        require = function(deps, callback) { //模块入口方法
            /*url:需要加载的文件,deps,依赖模块*/
            var i = 0,
                params = [],
                count = 0; //未加载的模块计数器
            for (; i < deps.length; i++) {
                count++;
                (function(index) { //闭包保存i值
                    loadModule(deps[index], function(module) {
                        count--
                        params[index] = module
                        if (count == 0) {//为0则所有模块加载完毕
                            loadDone(params, callback)
                        }
                    })
                })(i);
            }
        },
        define = function(url, callback) { //定义模块方法
            cache[url].export = callback() //缓存
            cache[url].onload(cache[url].export) //执行回调
        },
        loadModule = function(url, callback) { //模块加载方法
            if (!cache[url]) { //如果不存在模块则加载并缓存
                cache[url] = {
                    onload: callback,
                    export: null
                };
                loadSript(config[url])
            } else {//否则直接从缓存中输出
                callback(cache[url].export)
            }
        },
        loadDone = function(params, callback) { //所有模块加载完毕
            callback.apply(null, params)
        },
        loadSript = function(url) { //加载js文件
            var script = document.createElement('script');
            script.async = true;
            script.type = 'text/javascript';
            script.src = url
            script.charset = 'UTF-8';
            document.querySelector('body').appendChild(script)
        };

  

    <script src="requireDemo.js"></script>
    <script src="demo.js"></script>

  requireDemo.js就是我们写的demo版本的amd的库,运行demo.js,看看log出现什么
  但是以上代码还存在许多问题,如:
  没有处理参数,字符串
  没有处理循环依赖问题
  没有处理CMD写法
  没有处理js文件加载状态
  define一个模块显示的声明id,应该可以忽略显示的声明id,如define(function(){}),有兴趣的同学可以参考司徒的文章getCurrentScript获得当前js执行文件名称
  还有其他许多问题,但是对我们理解amd的基本原理是足够了的,希望对同学们模块化开发有帮助

posted @ 2019-02-15 11:03  兜_兜  阅读(1557)  评论(0编辑  收藏  举报