摘要:大概原理就是異步加載一堆腳本文件,個(gè)人項(xiàng)目可以試試,企業(yè)項(xiàng)目使用請深思熟慮后再進(jìn)行嘗試。我了解到的方法來自于設(shè)計(jì)模式,作者是張容銘,因?yàn)橛X得這個(gè)挺好玩的,給大家分享一下。
大概原理就是異步加載一堆腳本文件,個(gè)人項(xiàng)目可以試試,企業(yè)項(xiàng)目使用請深思熟慮后再進(jìn)行嘗試。
我了解到的方法來自于《javascript設(shè)計(jì)模式》,作者是張容銘,因?yàn)橛X得這個(gè)挺好玩的,給大家分享一下。
既然要直接在網(wǎng)頁上實(shí)現(xiàn)模塊化,肯定需要異步添加腳本文件,所以需要解決兩個(gè)麻煩的問題:
依賴的模塊也有依賴怎么辦
如何知道異步添加的js文件加載的狀態(tài)
//main.js 不用關(guān)注細(xì)節(jié),快速了解下調(diào)用方式即可 m.module(["dom/index"], function (dom) { var test = document.getElementById("test") console.log(dom(test).attr("id")) dom(test).css({ "background": "#000", "color": "#fff" }) }) ...... //dom/css.js m.module("dom/css", ["shared/util"], function (util) { return function (ele, css, value) { if (util.isString(css)) { if (util.isNumber(value)) { return ele.style.css = value } return ele.style.css } else { for (var k in css) { ele.style[k] = css[k] } } } }) ...... //shared/util.js m.module("shared/util", function () { return { isNumber: function (num) { return num === (0 || num) && num.constructor === Number }, isString: function (str) { return str === ("" || str) && str.constructor === String } } })
下面就開始實(shí)現(xiàn)這個(gè)暴露出來的module函數(shù)
遵守規(guī)則將模塊的實(shí)現(xiàn)隱藏起來,創(chuàng)建一個(gè)閉包
(function(m){ var m = m() })(function(){ window.m = {} })工具函數(shù)
添加兩個(gè)工具函數(shù),loadScript和getUrl
//加載腳本 var loadScript = function (src) { var _script = document.createElement("script") _script.type = "text/javascript" _script.async = true _script.src = src document.getElementsByTagName("head")[0].appendChild(_script) }, //為地址添加一個(gè).js getUrl = function (moduleName) { return String(moduleName).replace(/.js$/g, "") + ".js" }module函數(shù)的實(shí)現(xiàn)
通過上面的圖片示例可以了解到,module函數(shù)包括了創(chuàng)建和調(diào)用模塊的功能,它擁有三個(gè)參數(shù)
url 地址
deps 數(shù)據(jù)類型為數(shù)組的依賴模塊
callback 該模塊的主函數(shù)
獲取參數(shù)
m.module=function(){ var args = [].slice.call(arguments), //取最后一個(gè)參數(shù),即callback callback = args.pop(), //獲取依賴,且數(shù)據(jù)類型為數(shù)組 deps = (args.length && args[args.length - 1] instanceof Array) ? args.pop() : [], //地址 url = args.length ? args.pop() : null ...
這就是完整module函數(shù)的實(shí)現(xiàn),初看很復(fù)雜,別急,module的關(guān)鍵就在于下面的兩個(gè)函數(shù)(loadModule和setModule),凡是異步原理都是在和大腦作對,習(xí)慣就是新世界的大門,不要拘泥于閱讀順序
m.module = function () { var args = [].slice.call(arguments), callback = args.pop(), deps = (args.length && args[args.length - 1] instanceof Array) ? args.pop() : [], url = args.length ? args.pop() : null params = [],//依賴模塊序列,主函數(shù)(回調(diào)函數(shù))的使用的參數(shù) depsCount = 0,//該模塊未加載完畢的依賴數(shù)量 i = 0 if (deps.length) { while (i < deps.length) { //閉包保存i (function (i) { //這樣每個(gè)腳本執(zhí)行的module都會有一個(gè)depsCount depsCount++ //loadModule初始化是不會調(diào)用它的回調(diào)函數(shù)(緩沖器)的(可以先翻到下面看loadModule的實(shí)現(xiàn)) //但它會把回調(diào)函數(shù)添加到moduleCache中去,同時(shí)加載該依賴的腳本 loadModule(deps[i], function (mod) { //這里的mod是依賴模塊的輸出 params[i] = mod //等于0的時(shí)候就會執(zhí)行自己的回調(diào) depsCount-- if (depsCount === 0) { //將依賴模塊的輸出添加到callback的參數(shù)中,這樣主函數(shù)就可以直接使用參數(shù)進(jìn)行調(diào)用 setModule(url, params, callback) } }) })(i) i++ } } else { //一旦依賴走到底部,也就是一個(gè)腳本文件里的模塊沒有了依賴(可以先看看下面setModule) //loadModule初始化添加到moduleCache的回調(diào)就會執(zhí)行,而depsCount就會-1 setModule(url, [], callback) } }
如果沒有依賴的話,會直接執(zhí)行setModule,該模塊如果是被依賴的模塊,就會調(diào)用loadModule緩存的緩沖器,也就是它的回調(diào)函數(shù)
可以先看看loadModule和setModule的實(shí)現(xiàn)
if(deps.length){ ... }else{ setModule(url, [], callback) }
添加一個(gè)moduleCache變量,用于緩存模塊
//閉包內(nèi)部 var moduleCache = {}
var setModule = function (moduleName, params, callback) { var _module, fn if (moduleCache[moduleName]) { _module = moduleCache[moduleName] _module.status = "loaded" //export是模塊的輸出 _module.exports = callback ? callback.apply(_module, params) : null while (fn = _module.onload.shift()) { //執(zhí)行回調(diào),并將自己的模塊輸出到緩沖器中 fn(_module.exports) } } else { callback && callback.apply(null, params) } }
//這里參數(shù)callback不是主函數(shù),而是保存的緩沖器,詳細(xì)翻回module的完整函數(shù) var loadModule = function (moduleName, callback) { var _module //已初始化 if (moduleCache[moduleName]) { _module = moduleCache[moduleName] if (_module.status === "loaded") { //有就直接從moduleCache緩存中獲取 setTimeout(callback(_module.exports), 4) } else { _module.onload.push(callback) } } else { //初始化 moduleCache[moduleName] = { //地址,也可以叫模塊名稱 moduleName: moduleName, status: "loading", //該模塊return 的輸出 exports: null, onload: [callback] } //添加腳本 loadScript(getUrl(moduleName)) } }
第一次寫文章,如果覺得不好理解或者有行文不嚴(yán)謹(jǐn)?shù)牡胤娇梢园l(fā)下評論或者私信我修改
有幫助的話給我個(gè)贊哦
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/104043.html
摘要:注意,是叫做,不是。兩款瀏覽器同根同源,它們有著同樣的,但配色不同,由藍(lán)紅綠黃四種顏色組成,而由不同深度的藍(lán)色構(gòu)成。另外是基于的新特性實(shí)現(xiàn)的,所以它的一些執(zhí)行也支持異步操作,效率相對于來說也提高了。是否響應(yīng)信號,一般是命令,默認(rèn)是。 如果大家對 Python 爬蟲有所了解的話,想必你應(yīng)該聽說過 Selenium 這個(gè)庫,這實(shí)際上是一個(gè)自動化測試工具,現(xiàn)在已經(jīng)被廣泛用于網(wǎng)絡(luò)爬蟲中來應(yīng)對 ...
摘要:相比于開發(fā)人員的數(shù)量,目前框架類庫和工具的數(shù)量似乎更多一些。本文將會討論目前最為流行的客戶端框架類庫和工具以及它們之間的基本差異。典型的類庫包括字符串處理日期元素事件動畫網(wǎng)絡(luò)請求等功能。所以不需要明確的區(qū)分類庫框架和工具。 相比于JavaScript開發(fā)人員的數(shù)量,目前JavaScript框架、類庫和工具的數(shù)量似乎更多一些。截至2017年5月,GitHub上的快速搜索顯示,有超過110...
摘要:公司始于名為的平臺即服務(wù)供應(yīng)商。跨多個(gè)機(jī)器之間協(xié)調(diào)這些容器需要額外的工具,這稱之為容器編排。的核心優(yōu)勢是為應(yīng)用程序開發(fā)人員提供了用于編排無狀態(tài)容器的強(qiáng)大工具。有無數(shù)的文章都在討論和比較Docker、Kubernetes 以及Mesos。如果你是初學(xué)者,那么你可能會認(rèn)為這三個(gè)開源項(xiàng)目正為了稱霸容器界而殊死搏斗。雖然這三種技術(shù)都使得使用容器部署、管理和伸縮應(yīng)用成為可能,但實(shí)際上它們各自解決了不同...
摘要:就在最近,這項(xiàng)技術(shù)在流行地?zé)o監(jiān)督學(xué)習(xí)數(shù)據(jù)集上實(shí)現(xiàn)了非常好的結(jié)果。雖然這項(xiàng)工作并不針對無監(jiān)督學(xué)習(xí),但是它可以用作無監(jiān)督學(xué)習(xí)。利用替代類別的無監(jiān)督學(xué)習(xí)視覺表征使用圖像不行來創(chuàng)建非常大的替代類。 如今深度學(xué)習(xí)模型都需要在大規(guī)模的監(jiān)督數(shù)據(jù)集上訓(xùn)練。這意味著對于每一個(gè)數(shù)據(jù),都會有一個(gè)與之對應(yīng)的標(biāo)簽。在很流行的 ImageNet 數(shù)據(jù)集中,其共有一百萬張帶人工標(biāo)注的圖片,即 1000 類中的每一類都有 ...
閱讀 3495·2021-11-24 11:17
閱讀 2281·2021-11-15 11:38
閱讀 3367·2021-10-14 09:42
閱讀 2930·2019-08-30 15:54
閱讀 2024·2019-08-28 18:09
閱讀 539·2019-08-26 11:48
閱讀 1633·2019-08-26 10:48
閱讀 2147·2019-08-26 10:45