摘要:最后將執行的結果暴露給對象。腳本事件在腳本執行的時候不會立馬觸發解決辦法是通過腳本的來判斷總結以上就是對的一個大致的分析,如有錯誤,歡迎指出。
Seajs是一款模塊化開發框架,遵循CMD規范。雖然到現在為止很多模塊打包工具比它更加的完善,但還是有必要拜讀一下的,畢竟為前端模塊化的發展做了很大的貢獻,分析一下漲漲姿勢。
文章主要從以下幾個方面來分析。有不對的地方,歡迎大家指出。
CMD(Common Module Definition)是seajs在推廣中規范出來的。詳情請看 CMD模塊定義規范
2、模塊化開發的好處2.1、提高代碼可維護性
2.2、按需加載
2.3、避免變量污染
2.4、為前端工程化發展打下基礎
3、seajs是如何加載模塊,如何設計api的先在瀏覽器控制臺中打印下seajs這個全局變量,可以看到它掛載的一些對象和方法。讓我們先對它有個整體的感受
seajs 從use函數開始,到加載module的過程大致如下:
模塊加載完后瀏覽器會立馬執行define函數,這個函數比較有意思,先看源代碼
// Resolve id to uri Module.resolve = function(id, refUri) { // Emit `resolve` event for plugins such as text plugin var emitData = { id: id, refUri: refUri } emit("resolve", emitData) return emitData.uri || seajs.resolve(emitData.id, refUri) } // Define a module Module.define = function (id, deps, factory) { var argsLen = arguments.length // define(factory) if (argsLen === 1) { factory = id id = undefined } else if (argsLen === 2) { factory = deps // define(deps, factory) if (isArray(id)) { deps = id id = undefined } // define(id, factory) else { deps = undefined } } // Parse dependencies according to the module factory code if (!isArray(deps) && isFunction(factory)) { deps = parseDependencies(factory.toString()) } var meta = { id: id, uri: Module.resolve(id), deps: deps, factory: factory } // Try to derive uri in IE6-9 for anonymous modules if (!meta.uri && doc.attachEvent) { var script = getCurrentScript() if (script) { meta.uri = script.src } // NOTE: If the id-deriving methods above is failed, then falls back // to use onload event to get the uri } // Emit `define` event, used in nocache plugin, seajs node version etc emit("define", meta) meta.uri ? Module.save(meta.uri, meta) : // Save information for "saving" work in the script onload event anonymousMeta = meta }
有意思的是如果factory是個函數,同時deps不是一個數組,那么會將factory序列化,然后通過正則匹配從其中解析出依賴
var REQUIRE_RE = /"(?:"|[^"])*"|"(?:"|[^"])*"|/*[Ss]*?*/|/(?:/|[^/ ])+/(?=[^/])|//.*|.s*require|(?:^|[^$])requires*(s*([""])(.+?)1s*)/g var SLASH_RE = //g function parseDependencies(code) { var ret = [] code.replace(SLASH_RE, "") .replace(REQUIRE_RE, function(m, m1, m2) { if (m2) { ret.push(m2) } }) return ret }
解析依賴后會扔到模塊緩存系統中。之前模塊加載的時候就可以看到,主模塊加載完之后會執行factory函數。在執行factory函數的時候,會執行require加載的依賴。而require函數會判斷模塊狀態是否已經執行過了,如果不是那么就加載依賴,加載完后執行依賴。最后將執行的結果暴露給exports對象。
到此,seajs的整個加載執行過程已經分析完畢。相比requirejs,seajs代碼不是很多,但是能夠感受到代碼組織起來的精妙之處。
seajs解決模塊的互相依賴是通過緩存系統和模塊的狀態來實現的。
5、seajs如何解決瀏覽器兼容性問題5.1、onload 事件在 webkit<535.23和firfox<9.0中不支持
// `onload` event is not supported in WebKit < 535.23 and Firefox < 9.0 // ref: // - https://bugs.webkit.org/show_activity.cgi?id=38995 // - https://bugzilla.mozilla.org/show_bug.cgi?id=185236 // - https://developer.mozilla.org/en/HTML/Element/link#Stylesheet_load_events var isOldWebKit = +navigator.userAgent .replace(/.*(?:AppleWebKit|AndroidWebKit)/(d+).*/, "$1") < 536
解決的辦法是通過一個定時器,去監聽link節點是否已經加載,并且解析完。
5.2、腳本onload事件在腳本執行的時候不會立馬觸發
function getCurrentScript() { if (currentlyAddingScript) { return currentlyAddingScript } // For IE6-9 browsers, the script onload event may not fire right // after the script is evaluated. Kris Zyp found that it // could query the script nodes and the one that is in "interactive" // mode indicates the current script // ref: http://goo.gl/JHfFW if (interactiveScript && interactiveScript.readyState === "interactive") { return interactiveScript } var scripts = head.getElementsByTagName("script") for (var i = scripts.length - 1; i >= 0; i--) { var script = scripts[i] if (script.readyState === "interactive") { interactiveScript = script return interactiveScript } } }
解決辦法是通過腳本的readyState===‘interactive’來判斷
6、總結以上就是對seajs的一個大致的分析,如有錯誤,歡迎指出。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93001.html
摘要:本文主要簡單地解讀一下的源碼和模塊化原理。其中,是這次源碼解讀的核心,但我也會順帶介紹一下其他文件的作用的。對代碼比較簡單,其實就是聲明一下全局的命名空間。然而,真正的核心在于處理模塊依賴的問題。 seajs 簡單介紹 seajs是前端應用模塊化開發的一種很好的解決方案。對于多人協作開發的、復雜龐大的前端項目尤其有用。簡單的介紹不多說,大家可以到seajs的官網seajs.org參看...
摘要:依賴信息是一個數組,比如上面的依賴數組是源碼如下是利用正則解析依賴的一個函數時間出發函數主要看這個部分注釋是防止拷貝該時間的回調函數,防止修改,困惑了一下。對的賦值需要同步執行,不能放在回調函數里。 sea.js想解決的問題 惱人的命名沖突 煩瑣的文件依賴 對應帶來的好處 Sea.js 帶來的兩大好處: 通過 exports 暴露接口。這意味著不需要命名空間了,更不需要全局變量。...
摘要:這里的依賴都是通過來異步加載的,加載完畢之后立刻執行函數,在模塊文件執行完畢后包括和其他代碼,觸發的事件。 入口 seajs.use seajs.use直接調用Module.use(),Module.use的源碼如下: // Use function is equal to load a anonymous module // ids:模塊標識,uri是dirname + _us...
摘要:如果這個模塊的時候沒有設置,就表示是個匿名模塊,那怎么才能與之前發起請求的那個相匹配呢這里就有了一個全局變量,先將元數據放入這個對象。模塊加載完畢的回調保存元數據到匿名模塊,為請求的不管是不是匿名模塊,最后都是通過方法,將元數據存入到中。 近幾年前端工程化越來越完善,打包工具也已經是前端標配了,像seajs這種老古董早已停止維護,而且使用的人估計也幾個了。但這并不能阻止好奇的我,為了了...
閱讀 2770·2021-11-23 09:51
閱讀 3529·2021-10-08 10:17
閱讀 1262·2021-10-08 10:05
閱讀 1310·2021-09-28 09:36
閱讀 1833·2021-09-13 10:30
閱讀 2174·2021-08-17 10:12
閱讀 1670·2019-08-30 15:54
閱讀 2004·2019-08-30 15:53