|
- 项目目录
- 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>
-
-
-
- </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
来源:https://www.cnblogs.com/littleboyck/p/amd.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|