回首蕭瑟,殘月掛角,孤草弄影。javascript
看了一下上一篇隨筆的日期,距離上一篇日誌又過去了許久。在這段時間中,我盡全力去拯救那間便利店,惋惜到最後依然失敗,這一次是全部的出路所有沒有了,我也作了全部的努力。閒下來來了,補篇日誌吧。前端
今天想寫的是js中的AMD規範。AMD,即Asynchronous Module Definition的縮寫,它是前端代碼大爆炸後,爲了更好的管理js代碼所作出的一種努力。它來源於commonjs,一個野心勃勃的組織。發展至今已經爲許多著名的js庫所使用。我最早接觸它是在使用nodejs+express+jade進行web編輯的時候,後來一時興趣又接觸到了dojo,再而後jquery也開始使用AMD來組織代碼。昨天在翻看園子裏面js的文章的時候,又看到Sea.js這個代碼庫,看了一下,它是AMD的一個實踐,這也是我寫這篇日誌的原由。java
AMD規範從名字來看,模塊化和異步是他的核心。事物的發展是由需求驅動的,js的發展也同樣。在前端的js大爆炸以後,js的代碼量愈來愈大,問題也不斷的出現—功能邊界模糊,命名衝突,依賴混亂,代碼冗餘等等。AMD在功能模塊話的基礎上進化而來,用模塊管理功能,用異步的方式加載模塊。說了這麼多,那麼AMD的代碼定義是什麼呢?node
define([module-name?], [array-of-dependencies?], [module-factory-or-object])jquery
就是上面的一行API。很簡單的一行,實現起來也不難。我本身就仿照這個造過一個木輪子,思路以下:web
全局對象:$libs(object),require(function),模塊函數塊中要公開的對象所有懸掛於$libs上,使用require('module Name')得到接口;express
核心對象:module(moduleName,refFunc,refModules);app
js文件加載與通知(原生js,爲了簡單,沒有使用addEventListener,使用=進行事件掛載)異步
createScripts:function(moduleName){ var sc = document.createElement("script"); sc.setAttribute("type", "text/javascript"); sc.src = setting.getModulePath(moduleName); sc.onload = sc.onreadystatechange = this.reached; sc.onerror = this.error; document.body.appendChild(sc); }
reached:function(event){ var node = event?event.target:window.event.srcElement; if(!node.readyState || node.readyState == "loaded" || node.readyState == "complete"){ mfMatrix.update(setting.getModuleName(node.getAttribute("src")),"success"); node.onload = node.onreadystatechange = null; node.parentNode.removeChild(node); } }
模塊執行:executeModule(module),關鍵在於參數傳入模塊化
function executeModule(module){ if(module.refModules.length == 0){ module.refFunc(); return; } var prs = []; var order = "module.refFunc("; for(var i = 0;i!=module.refModules.length;i++){ prs.push(eval("require('"+module.refModules[i]+"')")); order += "prs["+i+"]"; if(i < module.refModules.length - 1) paras+=','; } order +=")"; eval(order); }
上面也說了,這是一個木輪子,僅供參考,要想投入實用,還有一些細節要處理,好比模塊名稱與js文件名稱的轉換,js文件加載失敗後的從新再次加載處理錯誤捕捉等等,都是應該考慮的問題。