同步模塊模式SMD
是請求發出後,不管模塊是否存在,當即執行後續的邏輯,實現模塊開發中對模塊的當即引用,模塊化是將複雜的系統分解爲高內聚、低耦合模塊,同步模塊模式不屬於通常定義的23
種設計模式的範疇,而一般將其看做廣義上的架構型設計模式。javascript
同步模塊模式一般用來解決以下場景的問題,隨着頁面功能的增長,系統的業務邏輯愈來愈複雜,多人開發的功能常常耦合在一塊兒,有時項目經理提出的需求,分配給多人實現的時候,經常由於某一處功能耦合了多人的代碼,從而出現排隊修改的現象。
經過使用模塊化來分解複雜的系統能夠很好的去解決這個問題,要想實現模塊化開發,首先就須要有一個模塊管理器,其管理着模塊的建立與調度,對於模塊的調用分爲兩類,第一類就是同步的模塊調度,實現相對比較簡單,不須要考慮模塊間的異步加載,第二類的異步模塊調度就比較繁瑣,其能夠實現對模塊的加載調度。java
// 定義模塊管理器單體對象 var F = F || {}; // 建立模塊的方法define // str 模塊路由; fn 模塊方法 F.define = function(str, fn){ // 定義模塊方法,本應該在閉包中定義,這裏先忽略 let parts = str.split("."); // 解析模塊路由str // 若是在閉包中,爲了屏蔽對模塊的直接訪問,建議將模塊添加給閉包內部私有變量 // old,當前模塊的祖父模塊;parent,當前模塊父模塊 let old = this; let parent = this; // i模塊層級,len模塊層級長度 let i = 0; // 若是第一個模塊是模塊管理器單體對象,則移除 if(parts[0] === "F") parts = parts.slice(1); // 屏蔽對define與module模塊方法的重寫 if(parts[0] === "define" || parts[0] === "module") return void 0; // 遍歷路由器並定義每層模塊 for(let len = parts.length; i < len; i++){ // 若是父模塊中不存在當前模塊,聲明當前模塊 if(parent[parts[i]] === void 0) parent[parts[i]] = {}; // 緩存下一級的祖父模塊 old = parent; // 緩存下一級的父模塊 parent = parent[parts[i]]; } // 若是給定模塊方法fn則定義改模塊方法 if(fn){ // 此時i等於parts.length,故減1 old[parts[--i]] = fn(); } return this; // 返回模塊管理器單體對象 } // 用上面的方法來建立模塊 // 建立模塊k,並對該模塊提供t方法 F.define("k", function(){ return { t: function(){ console.log("it is function t") } } //也能夠以構造函數的方法返回 /* let xx = function(){}; xx.t = function(){ console.log("this is xx.t") } xx.tt = function(){ console.log("this is xx.tt") } return xx; */ }); // 使用t方法,但正式的模塊開發不容許直接調用 // 一是由於模塊一般爲閉包中的私有變量,不會保存在F上,獲取不到,這裏簡化沒有使用閉包 // 二是由於這樣調用不符合模塊開發規範 F.k.t(); // 用構造函數返回時的調用方法 /* F.k.t(); F.k.tt(); */ // 也可先聲明模塊再定義方法 F.define("a.b") F.a.b = function(){ console.log("this is function from a.b") } F.a.b(); // 因爲不能直接調用,就須要調用模塊的方法 // 調用模塊的方法module // 參數分兩部分,依賴模塊與回調函數(最後一個參數) // 原理是遍歷獲取全部依賴模塊,並保存在依賴模塊列表中,而後將這些依賴模塊做爲參數傳入執行函數中執行 F.module = function(...args){ let fn = args.pop(); // 獲取回調執行函數 // 獲取依賴模塊,若args[0]是數組,則它爲依賴模塊,不然爲args let parts = args[0] && args[0] instanceof Array ? args[0] : args; let modules = []; // 依賴模塊列表 let modIDs = ""; // 模塊路由 let i = 0; // 依賴模塊索引 let ilen = parts.length; // 依賴模塊長度 // 遍歷依賴模塊 parts.forEach(v => { if(typeof v === "string"){ // 若是是模塊路由 let parent = this; // 設置當前模塊父對象(F) // 解析模塊路由,並屏蔽掉模塊父對象 modIDs = v.replace(/^F./, "").split("."); // 遍歷模塊路由層級 for(let j = 0; j < modIDs.length; j++){ parent = parent[modIDs[j]] || false; // 重置父模塊 } modules.push(parent); // 將模塊添加到模塊依賴列表 }else{ // 若是是模塊對象 modules.push(v); // 直接加入模塊依賴列表 } }) fn.apply(null, modules); // 執行回調函數 } // 依賴dom和k模塊的方法,數組形式 F.module(["dom", "k"], function(){ console.log(1); }) // 依賴dom2模塊和k.a方法,字符串形式 F.module("dom2", "k.a", function(){ console.log(2); })
https://github.com/WindrunnerMax/EveryDay
https://www.jianshu.com/p/2359390737aa https://www.dazhuanlan.com/2020/03/09/5e65fa05c9bb7/ https://blog.csdn.net/WuLex/article/details/107350493