项目目录      src        view1          index.html          main.js        view2      plugins        module.js        jquery.js        ......      modules // amd模块文件         a1.js        b1.js        c.js        b2.js        b21.js

src/view1/index.html

<!DOCTYPE html>    <html lang="en">    <head>        <meta charset="UTF-8">        <meta http-equiv="X-UA-Compatible" content="IE=edge">        <meta name="viewport" content="width=device-width, initial-scale=1.0">        <title>Document</title>    </head>    <body>        <!-- 引入amd插件-->        <!-- amd都有一个入口文件,我这里设计的方式是:自动引入同级目录下的main.js-->              <script src="/plugins/module.js"></script>    </body>    </html>

src/view1/main.js

module.configs({    baseUrl: '../modules'}).require(['a1','a2'], function(a2) {    console.log('a2: ', a2)})

plugins/module.js

    // 使用IIFE    (function(win){        function module(){            this.context = {                baseUrl: './',                alias: {},                entry: 'main.js',                suffix: '.js',            }            this.deps = {};            this.srcs = [];            this.customEvt = new module.CustomEvt();            this.ready();        }        var utils = module.utils = {            each(arr, callback){                var keys = Object.keys(arr);                for(var i = 0; i < keys.length; i++) {                     if(callback.call(arr, arr[i], i) === false) {                        break;                    }                }            },            // 只保留指定的keys            inKeys(target, keys) {                return Object.keys(target).reduce((newData, key) => {                    if (keys.includes(key)) {                        newData[key] = target[key];                    }                    return newData;                }, {});            },            // 路径拼接            pathJoin(...paths){                let path = '';                for(let i = paths.length - 1; i > -1; i--) {                    let pathItem = paths[i].replace(/\/+$/, '');                    // 如果是绝对路径                    if(/^\//.test(pathItem)) {                        path = pathItem + '/'+ path;                        break;                    }                    // 如果是相对路径                    if(/^\.\//.test(pathItem)) {                        pathItem = pathItem.slice(2)                    }                    // 如果是: ../../a/b/c                    if(/^(\.{2}\/)+\S+/.test(pathItem) && paths[i-1]) {                        let matches = null;                        while(matches = /^\.{2}\/(\S+)/.exec(pathItem)) {                            pathItem = matches[1];                            let prevPath = paths[i-1].replace(/\/+$/, '');                            if(prevPath) {                                paths[i-1] = prevPath.slice(0, prevPath.lastIndexOf('/'))                            }                        }                    }                    path = pathItem + '/'+ path;                }                return path.replace(/\/+$/, '');            },            createScript(src) {                var node = document.createElement('script');                node.type = 'text/javascript';                node.async = true;                node.src = src;                return node;            },            // 判断所有依赖是否加载完成            isDepsDone(options) {                var { depsTree, entry = depsTree.entry, deps } = options;                var deps = deps || depsTree[entry].deps;                var done = true;                utils.each(deps, function(moduleName) {                    var dep = depsTree[moduleName];                    if(dep) {                        if(dep.deps.length > 0) {                            done = utils.isDepsDone({                                depsTree,                                entry,                                deps: dep.deps                            });                            if(!done) {                                return false;                            }                        }                    }else {                        done = false;                        return false;                    }                });                return done;            }        }        var CustomEvt = function(){            this.subEvents = {};        };        CustomEvt.prototype = {            constructor:CustomEvt            ,$emit:function(event,data){                event = this.subEvents[event];                if(event){                    for(let i = 0; i < event.length; i++){                        event[i].apply(this, data);                    }                }                return this;            }            ,$on:function(event,handle){                let subEvents = this.subEvents;                !(event in subEvents) && (subEvents[event] = [])                subEvents[event].push(handle);                return this;            }            ,$off:function(event,handle){                let events = this.subEvents[event];                if(!handle){                    events && Reflect.deleteProperty(this.subEvents, event);                }else{                    if(typeof handle == 'function' && events){                        for(let i = 0,len = events.length; i < len; i++){                            let event = events[i];                            if(event == handle){                                return events.splice(i,1);                            }                        }                     }                }                return this;            }        }        module.CustomEvt = CustomEvt;        // // 主题对象        // function Subject() {        //     this.observers = [];        // }        // // 添加观察者        // Subject.prototype.addObserver = function(observer) {        //    !this.observers.includes(observer) && this.addObserver.push(observer);        // }        // Subject.prototype.notify = function(message) {        //     this.observers.forEach(observer => {        //         observer.update(message);//观察者接收消息的方法        //     })        // }        // function Observer() {}        // Observer.prototype.update = function(message) {        // }        Object.assign( module.prototype, {            // 入口函数            ready() {                this.setCtxProxy();                // 这里默认加载同级目录下的main.js,请确保main.js的存在                var script = utils.createScript(this.getUrl('./', this.entry));                document.body.appendChild(script);            },            // 设置context对象的属性,通过代理访问            setCtxProxy(){                var _self = this;                var ctx = this.context;                utils.each(Object.keys(ctx), function(key) {                    Object.defineProperty(_self, key, {                        get: function() {                            return ctx[key];                        },                        set: function(value) {                            if(ctx[key] !== value) {                                ctx[key] = value;                                return true;                            }                        }                    })                });            },            configs(options) {                Object.assign(this.context, utils.inKeys(options, ['baseUrl', 'alias', 'entry']))                return this;            },            getUrl(baseUrl, moduleName) {                var path = utils.pathJoin(baseUrl, moduleName);                return new RegExp('\\'+this.suffix+'$').test(path) ? path : path + this.suffix;            },            // 核心方法:define,收集依赖            define(moduleName, deps, factory) {                typeof deps == 'function' && (                    factory = deps,                    deps = []                )                if(!this.deps[moduleName]) {                    this.deps[moduleName] = {                        moduleName,                        deps,                        factory                    };                }            },            // 核心方法            // 迭代收集每一个入口依赖            traverseDeps(deps, callback){                var _self = this;                function buildDepsRelation(moduleName, depsTree) {                    var oldDepsTree = depsTree;                    var module = _self.deps[moduleName];                    depsTree = depsTree || { entry: moduleName };                    depsTree[moduleName] = module;                    if(module.deps.length > 0) {                        traverseScript(module.deps, depsTree);                    }else {                        // 所有依赖收集完,才返回                        if(utils.isDepsDone({ depsTree })) {                            typeof callback == 'function' && callback(depsTree);                        }                    }                    // 表示是第一层的递归,只重置第一层的递归                    if(!oldDepsTree) {                        depsTree = null;                    }                }                function traverseScript(deps, depsTree) {                    utils.each(deps, function(moduleName, i) {                        var curSrc = _self.getUrl(_self.baseUrl, moduleName);                        var isExistSrc = _self.srcs.includes(curSrc);                        // 判断相同的依赖是否已经加载过                        if(!isExistSrc) {                            _self.srcs.push(curSrc);                            var script = utils.createScript(curSrc);                            script.onload = function() {                                _self.customEvt.$emit('scriptLoaded', [moduleName])                                buildDepsRelation(moduleName, depsTree);                            }                            document.body.appendChild(script);                        }else {                            let curModuleName = moduleName;                            // 1,依赖已加载完成                            if(_self.deps[curModuleName]) {                                buildDepsRelation(moduleName, depsTree);                            }else {                                // 2,scriptLoad加载完成后,this.deps才有值                                _self.customEvt.$on('scriptLoaded', function(moduleName) {                                    if(moduleName == curModuleName) {                                        buildDepsRelation(moduleName, depsTree);                                    }                                });                            }                        }                    })                }                traverseScript(deps)            },            // 一次收集全部依赖树的依赖            getAllDeps(initDeps, callback) {                var _self = this;                function traverseDeps(deps) {                    utils.each(deps, function(moduleName) {                        var curSrc = _self.getUrl(_self.baseUrl, moduleName);                        var isExistSrc = _self.srcs.includes(curSrc);                        // 判断相同的依赖是否已经加载过                        if(!isExistSrc) {                            _self.srcs.push(curSrc);                            var script = utils.createScript(curSrc);                            script.onload = function() {                                var module = _self.deps[moduleName];                                if(module.deps.length > 0) {                                    traverseDeps(module.deps);                                }else {                                    // 所有依赖收集完,才返回                                    var isDone = initDeps                                    .map(entryDep => utils.isDepsDone({ depsTree: _self.deps, entry: entryDep }))                                    .every(isDone => isDone === true);                                    if(isDone){                                        typeof callback == 'function' && callback(_self.deps);                                    }                                }                            }                            document.body.appendChild(script);                        }else {                            // 所有依赖收集完,才返回                            var isDone = initDeps                            .map(entryDep => utils.isDepsDone({ depsTree: _self.deps, entry: entryDep }))                            .every(isDone => isDone === true);                            if(isDone){                                typeof callback == 'function' && callback(_self.deps);                            }                        }                    })                }                traverseDeps(initDeps)            },            require(deps, factory) {                typeof deps == 'string' && (deps = [deps]);                // 迭代收集每一个入口依赖                this.traverseDeps(deps, function(depsTree) {                    console.log(depsTree);                });                // 一次性收集所有依赖                // this.getAllDeps(deps, function(alldeps) {                //     console.log(alldeps)                // })            }        });        win.module = new module();    })(this);

源码链接:https://gitee.com/littleboyck/front/tree/master/front-module

联系方式:QQ: 1187253007