日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AMD加载器实现笔记(四)

發(fā)布時(shí)間:2025/5/22 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AMD加载器实现笔记(四) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

 繼續(xù)這一系列的內(nèi)容,到目前為止除了AMD規(guī)范中config的map、config參數(shù)外,我們已經(jīng)全部支持其他屬性了。這一篇文章中,我們來為增加對map的支持。同樣問題,想要增加map的支持首先要知道m(xù)ap的語義。

  

  主要用于解決在兩個(gè)不同模塊集中使用一個(gè)模塊的不同版本,并且保證兩個(gè)模塊集的交互沒有沖突。

  

  假設(shè)磁盤有如下文件:

  

  當(dāng)'some/newmodule'請求'foo'模塊時(shí),它將從foo1.2.js總得到'foo1.2'模塊;當(dāng)'some/oldmodule'請求'foo'模塊時(shí)它將從foo1.0中得到'foo1.0'模塊。

  在map屬性中可以使用任何的module ID前綴,并且mapping對象可以匹配任何別的module ID前綴。

  

  如果出現(xiàn)通配符‘*’,表示任何模塊使用這個(gè)匹配配置。通配符匹配對象中的模塊ID前綴可以被覆蓋。

?

  通過上文的解釋,可以明白,如果在'some/newmodule'中依賴的foo實(shí)際是上依賴的foo1.2。轉(zhuǎn)化成代碼邏輯應(yīng)當(dāng)是這樣的:如果在‘some/module’模塊中發(fā)現(xiàn)依賴foo模塊那就將foo替換成foo1.2。但是在什么地方實(shí)現(xiàn)替換好呢?因?yàn)槟K的定義從define開始,同時(shí)只有在define中才能獲得模塊的絕對路徑,所以我們把替換的處理放在define中。那么問題來了,我們的模塊大部分都是匿名模塊,模塊自己如何知道自己的模塊Id?所以一定要有一個(gè)標(biāo)記去告訴define函數(shù)當(dāng)前模塊的Id,我們知道每一個(gè)模塊都是一個(gè)JavaScript文件,每一個(gè)模塊都有一個(gè)對應(yīng)的script元素,所以最好的做法是沒每一個(gè)script都加一個(gè)自定義特性,來標(biāo)記當(dāng)前元素的模塊Id。

  所以在loadJs中要為script加自定義特性:


function loadJS(url, mId) {var script = document.createElement('script');script.setAttribute('data-moduleId', mId); //為script元素保留原始模塊Idscript.type = "text/javascript";//判斷模塊是否在paths中定義了路徑script.src = (url in global.require.parsedConfig.paths ? global.require.parsedConfig.paths[url] : url) + '.js';script.onload = function() {var module = modules[url];if (module && isReady(module) && loadings.indexOf(url) > -1) {callFactory(module);}checkDeps();};var head = document.getElementsByTagName('head')[0];head.appendChild(script);};
在define函數(shù)中,通過文件的絕對路徑,找出對應(yīng)的script元素,拿到模塊Id,判斷如果在map中,則進(jìn)行替換:


global.define = function(id, deps, callback) {//加上moduleId的支持if (typeof id !== "string" && arguments.length === 2) {callback = deps;deps = id;id = "";}var id = id || getCurrentScript();var script = document.querySelector('script[src="' + id + '"]');if (script || id in require.parsedConfig.shim) {var mId = script ? script.getAttribute('data-moduleId') : id;var maping = getMapSetting(mId);if (maping) {deps = deps.map(function(dep) {return maping[dep] || dep;});}}if (modules[id]) {console.error('multiple define module: ' + id);}require(deps, callback, id);};
function getMapSetting(mId) {if (mId in require.parsedConfig.map) {return require.parsedConfig[mId];} else if ('*' in require.parsedConfig.map) {return require.parsedConfig.map['*'];} else {return null;}};
目前為止,我們的加載器已經(jīng)支持了map屬性,完整代碼如下:

(function(global){global = global || window;modules = {};loadings = [];loadedJs = [];//module: id, state, factory, result, deps;global.require = function(deps, callback, parent){var id = parent || "Bodhi" + Date.now();var cn = 0, dn = deps.length;var args = [];var oriDeps = deps.slice();//保留原始dep的模塊Id// dep為非絕對路徑形式,而modules的key仍然需要絕對路徑deps = deps.map(function(dep) {if (modules[dep]) { //jquery return dep;} else if (dep in global.require.parsedConfig.paths) {return dep;}var rel = "";if (/^Bodhi/.test(id)) {rel = global.require.parsedConfig.baseUrl;} else {var parts = parent.split('/');parts.pop();rel = parts.join('/');}return getModuleUrl(dep, rel);});var module = {id: id,deps: deps,factory: callback,state: 1,result: null};modules[id] = module;if (checkCircleRef(id, id)) {return;}deps.forEach(function(dep, i) {if (modules[dep] && modules[dep].state === 2) {cn++args.push(modules[dep].result);} else if (!(modules[dep] && modules[dep].state === 1) && loadedJs.indexOf(dep) === -1) {loadJS(dep, oriDeps[i]);loadedJs.push(dep);}});if (cn === dn) {callFactory(module);} else {loadings.push(id);checkDeps();}};global.require.config = function(config) {this.parsedConfig = {};if (config.baseUrl) {var currentUrl = getCurrentScript();var parts = currentUrl.split('/');parts.pop();var currentDir = parts.join('/');this.parsedConfig.baseUrl = getRoute(currentDir, config.baseUrl);}var burl = this.parsedConfig.baseUrl;// 得到baseUrl后,location相對baseUrl定位this.parsedConfig.packages = [];if (config.packages) {for (var i = 0, len = config.packages.length; i < len; i++) {var pck = config.packages[i];var cp = {name: pck.name,location: getRoute(burl, pck.location)}this.parsedConfig.packages.push(cp);}}this.parsedConfig.paths = {};if (config.paths) {for (var p in config.paths) {this.parsedConfig.paths[p] = /^http(s)?/.test(config.paths[p]) ? config.paths[p] : getRoute(burl, config.paths[p]);}}this.parsedConfig.map = {};if (config.map) {this.parsedConfig.map = config.map;}this.parsedConfig.shim = {};//shim 要放在最后處理if (config.shim) {this.parsedConfig.shim = config.shim;for (var p in config.shim) {var item = config.shim[p];define(p, item.deps, function() {var exports;if (item.init) {exports = item.init.apply(item, arguments);}return exports ? exports : item.exports;});}}console.log(this.parsedConfig);}global.define = function(id, deps, callback) {//加上moduleId的支持if (typeof id !== "string" && arguments.length === 2) {callback = deps;deps = id;id = "";}var id = id || getCurrentScript();var script = document.querySelector('script[src="' + id + '"]');if (script || id in require.parsedConfig.shim) {var mId = script ? script.getAttribute('data-moduleId') : id;var maping = getMapSetting(mId);if (maping) {deps = deps.map(function(dep) {return maping[dep] || dep;});}}if (modules[id]) {console.error('multiple define module: ' + id);}require(deps, callback, id);};global.define.amd = {};//AMD規(guī)范function getMapSetting(mId) {if (mId in require.parsedConfig.map) {return require.parsedConfig[mId];} else if ('*' in require.parsedConfig.map) {return require.parsedConfig.map['*'];} else {return null;}};function checkCircleRef(start, target){var m = modules[start];if (!m) {return false;}var depModules = m.deps.map(function(dep) {return modules[dep] || null;});return depModules.some(function(m) {if (!m) {return false;}return m.deps.some(function(dep) {var equal = dep === target;if (equal) {console.error("circle reference: ", target, m.id);}return equal;});}) ? true : depModules.some(function(m) {if (!m) {return false;}return m.deps.some(function(dep) {return checkCircleRef(dep, target);});});//return hasCr ? true: };function getRoute(base, target) {var bts = base.replace(/\/$/, "").split('/'); //base dirvar tts = target.split('/'); //target partswhile (isDefined(tts[0])) {if (tts[0] === '.') {return bts.join('/') + '/' + tts.slice(1).join('/');} else if (tts[0] === '..') {bts.pop();tts.shift();} else {return bts.join('/') + '/' + tts.join('/');}}};function isDefined(v) {return v !== null && v !== undefined;};function getModuleUrl(moduleId, relative) {function getPackage(nm) {for (var i = 0, len = require.parsedConfig.packages.length; i < len; i++) {var pck = require.parsedConfig.packages[i];if (nm === pck.name) {return pck;}}return false;}var mts = moduleId.split('/');var pck = getPackage(mts[0]);if (pck) {mts.shift();return getRoute(pck.location, mts.join('/'));} else if (mts[0] === '.' || mts[0] === '..') {return getRoute(relative, moduleId);} else {return getRoute(require.parsedConfig.baseUrl, moduleId);}};function loadJS(url, mId) {var script = document.createElement('script');script.setAttribute('data-moduleId', mId); //為script元素保留原始模塊Idscript.type = "text/javascript";//判斷模塊是否在paths中定義了路徑script.src = (url in global.require.parsedConfig.paths ? global.require.parsedConfig.paths[url] : url) + '.js';script.onload = function() {var module = modules[url];if (module && isReady(module) && loadings.indexOf(url) > -1) {callFactory(module);}checkDeps();};var head = document.getElementsByTagName('head')[0];head.appendChild(script);};function checkDeps() {for (var p in modules) {var module = modules[p];if (isReady(module) && loadings.indexOf(module.id) > -1) {callFactory(module);checkDeps(); // 如果成功,在執(zhí)行一次,防止有些模塊就差這次模塊沒有成功}}};function isReady(m) {var deps = m.deps;var allReady = deps.every(function(dep) {return modules[dep] && isReady(modules[dep]) && modules[dep].state === 2;})if (deps.length === 0 || allReady) {return true;}};function callFactory(m) {var args = [];for (var i = 0, len = m.deps.length; i < len; i++) {args.push(modules[m.deps[i]].result);}m.result = m.factory.apply(window, args);m.state = 2;var idx = loadings.indexOf(m.id);if (idx > -1) {loadings.splice(idx, 1);}};function getCurrentScript(base) {// 參考 https://github.com/samyk/jiagra/blob/master/jiagra.jsvar stack;try {a.b.c(); //強(qiáng)制報(bào)錯(cuò),以便捕獲e.stack} catch (e) { //safari的錯(cuò)誤對象只有l(wèi)ine,sourceId,sourceURLstack = e.stack;if (!stack && window.opera) {//opera 9沒有e.stack,但有e.Backtrace,但不能直接取得,需要對e對象轉(zhuǎn)字符串進(jìn)行抽取stack = (String(e).match(/of linked script \S+/g) || []).join(" ");}}if (stack) {/**e.stack最后一行在所有支持的瀏覽器大致如下:*chrome23:* at http://113.93.50.63/data.js:4:1*firefox17:*@http://113.93.50.63/query.js:4*opera12:http://www.oldapps.com/opera.php?system=Windows_XP*@http://113.93.50.63/data.js:4*IE10:* at Global code (http://113.93.50.63/data.js:4:1)* //firefox4+ 可以用document.currentScript*/stack = stack.split(/[@ ]/g).pop(); //取得最后一行,最后一個(gè)空格或@之后的部分stack = stack[0] === "(" ? stack.slice(1, -1) : stack.replace(/\s/, ""); //去掉換行符return stack.replace(/(:\d+)?:\d+$/i, "").replace(/\.js$/, ""); //去掉行號與或許存在的出錯(cuò)字符起始位置}var nodes = (base ? document : head).getElementsByTagName("script"); //只在head標(biāo)簽中尋找for (var i = nodes.length, node; node = nodes[--i]; ) {if ((base || node.className === moduleClass) && node.readyState === "interactive") {return node.className = node.src;}}}; })(window)

 

  下面我們看一個(gè)demo:

  使用我們的加載器來加載jquery,同時(shí)禁用jquery的全局模式$:


window.something = "Bodhi";require.config({baseUrl: "./",packages: [{name: "more",location: "./more"}, {name: "mass",location: "../"}, {name: "wab",location: "../../../"}],shim: {"something": {"deps": ['jquery'],exports: 'something',init: function(jq, ol) {console.log(jq);console.log($);return something + " in shim";}}},map: {'*': {'jquery': 'jquery-private'},'jquery-private': {'jquery': 'jquery'}},paths: {'jquery': "../../Bodhi/src/roots/jquery"}});require(['bbb',//'aaa.bbb.ccc',//'ccc',//'ddd',//'fff','something'], function(aaabbbccc){console.log('simple loader');console.log(arguments);});
jquery-private代碼如下:


define(['jquery'], function(jquery) {return jquery.noConflict(true); });
如果某一模塊依賴jquery,那么將會(huì)加載jquery-private。而在jquery中,因?yàn)榕渲昧薽ap和paths,所以jquery-private中的jquery根據(jù)paths找到j(luò)query文件,并加載。同時(shí)在jquery-private中將禁用了全局模式之后的jquery對象返回給something模塊。通過這個(gè)配置所有的模塊在引用jquery時(shí),實(shí)際上是引用了jquery-private模塊。


總結(jié)

以上是生活随笔為你收集整理的AMD加载器实现笔记(四)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 97在线超碰| 男女插插插视频 | 综合精品久久久 | 欧美色拍| 国产精品3 | 亚洲成网站 | 九九超碰| 国产黄色网址在线观看 | 精品福利三区3d卡通动漫 | 日本高清视频www夜色资源 | 国产热视频 | 日本免费www| 国产拍拍拍拍拍拍拍拍拍拍拍拍拍 | 天堂а√在线最新版中文在线 | 色久影院 | 中文字幕av二区 | 毛片毛片毛片毛片毛片毛片毛片毛片毛片毛片 | 日韩av在线免费看 | 欧美色综合网 | 精品国产一区三区 | 五月天堂网 | 播色屋| 黄色喷水网站 | 不卡中文字幕在线观看 | 又黄又骚的视频 | 国产在线超碰 | 人人干视频 | 欧美一级片播放 | 女上男下动态图 | 亚洲经典视频在线观看 | 最新视频 - x88av | 含羞草一区二区三区 | 99黄色网 | 国产一区二区三区在线看 | 黄色大视频 | 羞羞的软件 | 精品国产一区二区三 | 国色综合 | 亚洲欧美另类在线视频 | 黄色三级免费观看 | 国产精品久久久影院 | 尤物在线视频观看 | 青青草原在线免费观看视频 | 狼友视频国产精品 | 欧美激情免费看 | 久久综合婷婷国产二区高清 | 久久久久美女 | 国产一区二区女内射 | 正在播放国产精品 | 男人桶女人桶爽30分钟 | 亚洲视频网站在线 | 97人妻精品一区二区三区免 | 嫩草国产精品 | 美女视频久久久 | 欧美入口 | 女性生殖扒开酷刑vk | 在线观看中文字幕视频 | 麻豆视频免费在线 | 黄色免费片 | 在线观看欧美亚洲 | 日本黄色生活片 | 一本色道综合久久欧美日韩精品 | 日日燥夜夜燥 | 黄色成人小视频 | 日噜| 在线观看亚洲区 | 中文字幕第九页 | 成人av资源站| 男人天堂视频在线 | 成人在线网 | 国产男女视频在线观看 | 日韩污视频在线观看 | 欧美大片一区二区 | 成人看片免费 | 欧美国产三级 | 无码国模国产在线观看 | 国产精品久久久久久久久久久久久 | 日本三区在线 | 免费观看a级片 | 欧美整片在线 | 美女插插 | 成人在线观看www | 天堂婷婷 | 欧洲激情网 | 欧美日韩一区二区视频在线观看 | 成人免费视频国产 | www污网站 | 欧美裸体网站 | 美女三级黄色片 | 顶级毛片 | 免费男女视频 | 偷拍视频一区二区 | 欧美高清一区二区 | 中文字幕一二三四区 | 国产熟女精品视频 | 国产swag在线观看 | 老师的肉丝玉足夹茎 | 五月丁香综合激情六月久久 | av天天网|