摘要:最后將執(zhí)行的結(jié)果暴露給對象。腳本事件在腳本執(zhí)行的時候不會立馬觸發(fā)解決辦法是通過腳本的來判斷總結(jié)以上就是對的一個大致的分析,如有錯誤,歡迎指出。
Seajs是一款模塊化開發(fā)框架,遵循CMD規(guī)范。雖然到現(xiàn)在為止很多模塊打包工具比它更加的完善,但還是有必要拜讀一下的,畢竟為前端模塊化的發(fā)展做了很大的貢獻,分析一下漲漲姿勢。
文章主要從以下幾個方面來分析。有不對的地方,歡迎大家指出。
CMD(Common Module Definition)是seajs在推廣中規(guī)范出來的。詳情請看 CMD模塊定義規(guī)范
2、模塊化開發(fā)的好處2.1、提高代碼可維護性
2.2、按需加載
2.3、避免變量污染
2.4、為前端工程化發(fā)展打下基礎(chǔ)
3、seajs是如何加載模塊,如何設(shè)計api的先在瀏覽器控制臺中打印下seajs這個全局變量,可以看到它掛載的一些對象和方法。讓我們先對它有個整體的感受
seajs 從use函數(shù)開始,到加載module的過程大致如下:
模塊加載完后瀏覽器會立馬執(zhí)行define函數(shù),這個函數(shù)比較有意思,先看源代碼
// 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是個函數(shù),同時deps不是一個數(shù)組,那么會將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 }
解析依賴后會扔到模塊緩存系統(tǒng)中。之前模塊加載的時候就可以看到,主模塊加載完之后會執(zhí)行factory函數(shù)。在執(zhí)行factory函數(shù)的時候,會執(zhí)行require加載的依賴。而require函數(shù)會判斷模塊狀態(tài)是否已經(jīng)執(zhí)行過了,如果不是那么就加載依賴,加載完后執(zhí)行依賴。最后將執(zhí)行的結(jié)果暴露給exports對象。
到此,seajs的整個加載執(zhí)行過程已經(jīng)分析完畢。相比requirejs,seajs代碼不是很多,但是能夠感受到代碼組織起來的精妙之處。
seajs解決模塊的互相依賴是通過緩存系統(tǒng)和模塊的狀態(tài)來實現(xiàn)的。
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
解決的辦法是通過一個定時器,去監(jiān)聽link節(jié)點是否已經(jīng)加載,并且解析完。
5.2、腳本onload事件在腳本執(zhí)行的時候不會立馬觸發(fā)
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、總結(jié)以上就是對seajs的一個大致的分析,如有錯誤,歡迎指出。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/93001.html
摘要:本文主要簡單地解讀一下的源碼和模塊化原理。其中,是這次源碼解讀的核心,但我也會順帶介紹一下其他文件的作用的。對代碼比較簡單,其實就是聲明一下全局的命名空間。然而,真正的核心在于處理模塊依賴的問題。 seajs 簡單介紹 seajs是前端應(yīng)用模塊化開發(fā)的一種很好的解決方案。對于多人協(xié)作開發(fā)的、復(fù)雜龐大的前端項目尤其有用。簡單的介紹不多說,大家可以到seajs的官網(wǎng)seajs.org參看...
摘要:依賴信息是一個數(shù)組,比如上面的依賴數(shù)組是源碼如下是利用正則解析依賴的一個函數(shù)時間出發(fā)函數(shù)主要看這個部分注釋是防止拷貝該時間的回調(diào)函數(shù),防止修改,困惑了一下。對的賦值需要同步執(zhí)行,不能放在回調(diào)函數(shù)里。 sea.js想解決的問題 惱人的命名沖突 煩瑣的文件依賴 對應(yīng)帶來的好處 Sea.js 帶來的兩大好處: 通過 exports 暴露接口。這意味著不需要命名空間了,更不需要全局變量。...
摘要:這里的依賴都是通過來異步加載的,加載完畢之后立刻執(zhí)行函數(shù),在模塊文件執(zhí)行完畢后包括和其他代碼,觸發(fā)的事件。 入口 seajs.use seajs.use直接調(diào)用Module.use(),Module.use的源碼如下: // Use function is equal to load a anonymous module // ids:模塊標識,uri是dirname + _us...
摘要:如果這個模塊的時候沒有設(shè)置,就表示是個匿名模塊,那怎么才能與之前發(fā)起請求的那個相匹配呢這里就有了一個全局變量,先將元數(shù)據(jù)放入這個對象。模塊加載完畢的回調(diào)保存元數(shù)據(jù)到匿名模塊,為請求的不管是不是匿名模塊,最后都是通過方法,將元數(shù)據(jù)存入到中。 近幾年前端工程化越來越完善,打包工具也已經(jīng)是前端標配了,像seajs這種老古董早已停止維護,而且使用的人估計也幾個了。但這并不能阻止好奇的我,為了了...
閱讀 2784·2021-11-23 09:51
閱讀 3539·2021-10-08 10:17
閱讀 1273·2021-10-08 10:05
閱讀 1327·2021-09-28 09:36
閱讀 1846·2021-09-13 10:30
閱讀 2186·2021-08-17 10:12
閱讀 1682·2019-08-30 15:54
閱讀 2011·2019-08-30 15:53