九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
JS模塊化開(kāi)發(fā):使用SeaJs高效構(gòu)建頁(yè)面

一、扯淡部分

很久很久以前,也就是剛開(kāi)始接觸前端的那會(huì)兒,腦袋里壓根沒(méi)有什么架構(gòu)、重構(gòu)、性能這些概念,天真地以為前端===好看的頁(yè)面,甚至把js都劃分到除了用來(lái)寫(xiě)一些美美的特效別無(wú)它用的陰暗角落里,就更別說(shuō)會(huì)知道js還有面向?qū)ο?,設(shè)計(jì)模式,MVC,MVVM,模塊化,構(gòu)建工具等等這些高大上的概念了?,F(xiàn)在想想還真是Too young too naive。前兩天某大神在群里分享他招聘前端的心得的時(shí)候就說(shuō),就是那些以為能寫(xiě)兩個(gè)頁(yè)面就可以自稱前端的人拉低了行業(yè)水平。這樣看來(lái)前兩年我還真的扯了不少后腿呢

……

后來(lái)干這行干得稍久一些,發(fā)現(xiàn)水簡(jiǎn)直深深深深千尺,而且周圍遍布沼澤。即便爬到岸上,迎接你的又是大大小小各種坑??拥腎E6,坑爹的兼容,坑爹的瀏覽器特性……總之,任何一個(gè)前端都有被這些大大小小的坑虐到體無(wú)完膚的慘痛經(jīng)歷。但(我覺(jué)得這個(gè)但字是點(diǎn)睛之筆),生活在繼續(xù),時(shí)代在發(fā)展,競(jìng)爭(zhēng)依然殘酷,你不往前走就只能在這片沼澤里不斷下沉,最后掙扎的結(jié)果也不過(guò)是冒出水面兩個(gè)泡泡然后……爆掉。

在經(jīng)歷了會(huì)寫(xiě)頁(yè)面,會(huì)用js寫(xiě)效果的階段后,大多數(shù)人都已經(jīng)慢慢地能夠滿足產(chǎn)品提出的各種奇葩的功能需求,但僅僅是滿足了需求,而沒(méi)有考慮性能、團(tuán)隊(duì)協(xié)作、開(kāi)發(fā)消耗的各種成本等等這些問(wèn)題。有時(shí)候甚至寫(xiě)好的js再回頭去看時(shí)也會(huì)讓自己一頭霧水:各種方法,各種邏輯雜亂無(wú)章地糾纏在一起,根本理不清誰(shuí)調(diào)用了誰(shuí),誰(shuí)為誰(shuí)定義,誰(shuí)又是誰(shuí)的誰(shuí)!更可怕的是當(dāng)項(xiàng)目被其他小伙伴接管,每修改一處上線前都擔(dān)驚受怕:修改這里到底TM對(duì)不對(duì)???

還好前端領(lǐng)域開(kāi)路者們用他們的智慧朝我們艱難跋涉的水坑里扔了幾塊石頭:嘗試讓你的代碼模塊化吧~

二、js模塊化

為毛要嘗試模塊化開(kāi)發(fā)?

如今的網(wǎng)頁(yè)越來(lái)越像桌面程序,網(wǎng)頁(yè)上加載的javascript也越來(lái)越復(fù)雜,coder們不得不開(kāi)始用軟件工程的思維去管理自己的代碼。Javascript模塊化編程,已經(jīng)成為一個(gè)非常迫切的需求。理想情況下,開(kāi)發(fā)者只需要實(shí)現(xiàn)核心的業(yè)務(wù)邏輯,其他都可以加載別人已經(jīng)寫(xiě)好的模塊。但是,Javascript不是一種模塊化編程語(yǔ)言,它不支持"類"(class),更遑論"模塊"(module)了。(正在制定中的 ECMAScript標(biāo)準(zhǔn) 第六版將正式支持"類"和"模塊",但還需要很長(zhǎng)時(shí)間才能投入實(shí)用。)

——來(lái)自阮一峰的博文:《 Javascript模塊化編程(一):模塊的寫(xiě)法

上面其實(shí)已經(jīng)把 模塊化的意義和目的 已經(jīng)講述的很清楚了,所以就拿來(lái)主義,節(jié)省腦細(xì)胞留給下面的內(nèi)容

模塊化的概念出來(lái)以后,新的問(wèn)題又來(lái)了:需不需要一個(gè)統(tǒng)一的模塊化標(biāo)準(zhǔn)?我們來(lái)試想一下如果沒(méi)有標(biāo)準(zhǔn)的情況:A以自己的標(biāo)準(zhǔn)寫(xiě)了模塊Module1,然后B又以自己的標(biāo)準(zhǔn)寫(xiě)了Module2,恩,在他們看來(lái),這的確是模塊,但當(dāng)Module1想調(diào)用模塊Module2的時(shí)候該怎么調(diào)用呢?它們之間火星人與地球人交流,沒(méi)有同聲傳譯看起來(lái)依舊是毫無(wú)頭緒。于是模塊化規(guī)范便又成了一個(gè)問(wèn)題。

2009年美國(guó)的一位大神發(fā)明了 node.js (具體內(nèi)容自行腦補(bǔ),本文不作討論),用來(lái)開(kāi)發(fā)服務(wù)器端的js。我們都知道,傳統(tǒng)的服務(wù)器端開(kāi)發(fā)語(yǔ)言如PHP、JAVA等都必須進(jìn)行模塊化開(kāi)發(fā),JS想占據(jù)人家的地盤(pán)也不例外,模塊化是必須的,于是 commomJS 模塊化開(kāi)發(fā)規(guī)范誕生了,但這貨只是服務(wù)器端JS模塊化開(kāi)發(fā)的標(biāo)準(zhǔn),客戶端又沒(méi)用。

—有童鞋:bla了那么多,這跟我在客戶端進(jìn)行js模塊化開(kāi)發(fā)有毛關(guān)系???

—PO主:表著急,了解了這玩意兒的前世今生,用起來(lái)才能得心應(yīng)手~

服務(wù)器端JS模塊化規(guī)范有了,JSer們自然想到了能把commonJS規(guī)范拿到客戶端就好啦,而且最好兩者能夠兼容,一個(gè)模塊不用修改,在服務(wù)器和瀏覽器都可以運(yùn)行

。爽爆~但(這個(gè)但字又是一個(gè)點(diǎn)睛之筆),由于一個(gè)重大的局限,使得CommonJS規(guī)范不適用于瀏覽器環(huán)境。服務(wù)器端獲取資源的方式是本地讀取,而客戶端拿資源的方式是通過(guò)Http來(lái)獲取,這是一個(gè)大問(wèn)題,因?yàn)槟K都放在服務(wù)器端,瀏覽器等待時(shí)間取決于網(wǎng)速的快慢,可能要等很長(zhǎng)時(shí)間,瀏覽器處于"假死"狀態(tài)。因此,瀏覽器端的模塊,不能采用"同步加載"(synchronous),只能采用"異步加載"(asynchronous),于是誕生了AMD和CMD。

—有童鞋:核心內(nèi)容終于TMD來(lái)了,就是AMD和CMD這二貨

—PO主:……

三、AMD和CMD

AMD (Asynchronous Module Definition) :  RequireJS 在推廣過(guò)程中對(duì)模塊定義的規(guī)范化產(chǎn)出。

AMD用白話文講就是  異步模塊定義 ,對(duì)于 JSer 來(lái)說(shuō),異步是再也熟悉不過(guò)的詞了,所有的模塊將被異步加載,模塊加載不影響后面語(yǔ)句運(yùn)行。所有依賴某些模塊的語(yǔ)句均放置在回調(diào)函數(shù)中,等到依賴的模塊加載完成之后,這個(gè)回調(diào)函數(shù)才會(huì)運(yùn)行。

主要有兩個(gè)Javascript庫(kù)實(shí)現(xiàn)了AMD規(guī)范: require.jscurl.js 。

(本文主要分享的是SeaJs模塊化構(gòu)建方式,關(guān)于requireJs構(gòu)建方式請(qǐng)移步至:《 Javascript模塊化編程(一):模塊的寫(xiě)法 》)

CMD (Common Module Definition) : SeaJS 在推廣過(guò)程中對(duì)模塊定義的規(guī)范化產(chǎn)出。

實(shí)現(xiàn)了CMD規(guī)范的主要的Javascript庫(kù): Sea.js 。

CMD翻譯來(lái)就是  通用模塊定義 ,與AMD的相同點(diǎn):

1. 這些規(guī)范的目的都是為了 JavaScript 的模塊化開(kāi)發(fā),特別是在瀏覽器端的。

2. 目前這些規(guī)范的實(shí)現(xiàn)都能達(dá)成 瀏覽器端模塊化開(kāi)發(fā)的目的 。

當(dāng)然與AMD也有有兩點(diǎn)區(qū)別:

1. 對(duì)于依賴的模塊,AMD 是 提前執(zhí)行 ,CMD 是 延遲執(zhí)行 。不過(guò) RequireJS 從 2.0 開(kāi)始,也改成可以延遲執(zhí)行(根據(jù)寫(xiě)法不同,處理方式不同)。CMD 推崇 as lazy as possible( PO主:是越懶越好的意思么?

)。

2. CMD 推崇 依賴就近 ,AMD 推崇 依賴前置

—— SeaJs作者玉伯在知乎的回答

看代碼理解上面兩點(diǎn)的意思:

AMD模塊的定義方法

// AMD 默認(rèn)推薦的是define(['./a', './b'], function(a, b) { // 依賴必須一開(kāi)始就寫(xiě)好,即依賴前置,執(zhí)行完引入的模塊后才開(kāi)始執(zhí)行回調(diào)函數(shù)    a.doSomething()    // 此處略去 100 行    b.doSomething()    ...})

CMD模塊的定義方法:

// CMDdefine(function(require, exports, module) {  var a = require('./a')  a.doSomething()  // 此處略去 100 行  var b = require('./b') // 依賴可以就近書(shū)寫(xiě),即依賴就近,什么時(shí)候用到什么時(shí)候才引入  b.doSomething()  // ... })

好了,看過(guò)兩個(gè)例子,對(duì)于之前沒(méi)有接觸過(guò)模塊化開(kāi)發(fā)的童鞋來(lái)說(shuō)依舊是一頭霧水:那個(gè)define是什么東東啊?還有那個(gè)require,exports,module,都是干什么的?

表捉急,我們一步一步來(lái)。

在 CMD 規(guī)范中,一個(gè)模塊就是一個(gè)文件。代碼的書(shū)寫(xiě)格式如下:

define(factory);

來(lái)看github上CMD模塊定義規(guī)范上的解釋:

define 是一個(gè)全局函數(shù),用來(lái)定義模塊。

define 接受  factory  參數(shù), factory 可以是一個(gè) 函數(shù) ,也可以是一個(gè) 對(duì)象或字符串

factory 為對(duì)象、字符串時(shí), 表示模塊的接口就是該對(duì)象、字符串 。比如可以如下定義一個(gè) JSON 數(shù)據(jù)模塊:

1 define({ "foo": "bar" });

也可以通過(guò)字符串定義模板模塊:

1 define('I am a template. My name is {{name}}.');

factory 為函數(shù)時(shí),表示是 模塊的構(gòu)造方法 。執(zhí)行該構(gòu)造方法,可以得到模塊向外提供的接口。factory 方法在執(zhí)行時(shí),默認(rèn)會(huì)傳入三個(gè)參數(shù): require、exports 和 module

1 define(function(require, exports, module) {2   // 模塊代碼3 });

四、小例子

說(shuō)了半天概念應(yīng)該印象還不深刻,我們就來(lái)看一個(gè)例子用來(lái)演示sea.js的基本用法。首先define傳入的參數(shù)是對(duì)象和字符串的情況,我先舉一個(gè)參數(shù)的對(duì)象的例子,傳字符串大同小異。來(lái)看代碼:

1,我先來(lái)定義一個(gè)模塊m1.js:

define({a:"這里是屬性a的值"});

define傳入的是一個(gè)對(duì)象字面量?,F(xiàn)在這個(gè)東東就可以叫做一個(gè)模塊了~我想在頁(yè)面一加載的時(shí)候就把a(bǔ)的值alert出來(lái),怎么做呢?繼續(xù)往下看。

2,在頁(yè)面上引入這個(gè)模塊:

1 seajs.use('./m1.js',function(ex){2      alert(ex.a);3  }); //彈出“這里是屬性a的值”

翻譯得直白一點(diǎn),大意就是:

seajs : Hi~m1.js,我現(xiàn)在要用(use)你了,然后把你的公開(kāi)接口(exports)存到我回調(diào)函數(shù)的參數(shù)(ex)里,你把想給我調(diào)用的東東放到這個(gè)參數(shù)里吧~么么噠

m1.js : 好的,我定義的對(duì)象字面量放到接口里給你了,拿去盡管刷~

然后……a的值就彈出來(lái)了。很愉快的一次交易。 PS:頁(yè)面所調(diào)用的模塊就為整個(gè)web應(yīng)用的js入口。本例中js的入口就是m1.js。 接下來(lái)再來(lái)看看如果 define的參數(shù)是個(gè)函數(shù) 的情況。

1,先定義一個(gè)模塊m2.js:

1 define(function(require,exports,module){2     var var1 = "這是要alert出來(lái)的值";//私有變量,沒(méi)有通過(guò)接口返出去的其他模塊不能訪問(wèn)3     function alerts(){4         alert(var1);5     }6     exports.alerts = alerts;//將需要公開(kāi)的方法存入exports接口中7 });

2,在頁(yè)面上引入這個(gè)模塊并執(zhí)行模塊m2.js公開(kāi)的方法:

1 seajs.use('./m2.js',function(ex){2      ex.alerts();//ex中存的有m2.js中的公開(kāi)對(duì)象3 }); //彈出“這是要alert出來(lái)的值”

到這里可以簡(jiǎn)單地說(shuō)一下factory方法的三個(gè)形參的意義了(個(gè)人理解):

require :  提供了引入機(jī)制,提供了一種方式來(lái)建立依賴,和C中的include和java中的import類似;

exports :  提供了導(dǎo)出機(jī)制,提供了私有和共有分離,未使用exports語(yǔ)句導(dǎo)出的變量或者函數(shù),其他模塊即使引用此模塊也不能使用;

module :  提供了模塊信息描述。

是不是思路賤賤清晰了呢?剛才我們的例子中只是從頁(yè)面調(diào)用模塊的用法,模塊之間互相調(diào)用還沒(méi)有體現(xiàn),SO,接下來(lái)就以m1.js和m2.js兩個(gè)模塊作為例子來(lái)嘗試一下  模塊之間互相調(diào)用 。

1,首先m1.js模塊不變:

1 define({a:"這里是屬性a的值"});

2,m2.js模塊要依賴(require)m1.js:

1 define(function(require,exports,module){2     var var1 = "這是要alert出來(lái)的值";//私有變量,沒(méi)有通過(guò)接口返出去的其他模塊不能訪問(wèn)3     var var2 = require('./m1.js').a;//這里就是m2.js模塊調(diào)用m1.js的方式:var2的值等于當(dāng)前模塊所依賴的m1.js對(duì)外接口中屬性a的值4     function alerts(){5         alert(var2);6     }7     exports.alerts = alerts;//將需要公開(kāi)的方法存入exports接口中8 });

3,頁(yè)面上引入m2.js模塊(同上一個(gè)例子),結(jié)果就會(huì)把a(bǔ)的屬性值給alert出來(lái)~

五、實(shí)例:模塊化的拖拽個(gè)窗口縮放

當(dāng)然,上面幾個(gè)例子是簡(jiǎn)單到不能再簡(jiǎn)單的例子,估計(jì)親們也已經(jīng)看出來(lái)一些道道,但個(gè)人感覺(jué)還是沒(méi)能體現(xiàn)出 模塊化開(kāi)發(fā)的優(yōu)勢(shì) 。那下面就來(lái)看一個(gè)實(shí)例: 模塊化的拖拽個(gè)窗口縮放 。先看一下效果圖:

PS:效果圖中的紅色區(qū)域要先定縮放的范圍,即寬高0px-寬高500px 。要寫(xiě)這樣一個(gè)需求的例子,按照之前的編程習(xí)慣你會(huì)怎么寫(xiě)?反正在之前,我是會(huì)把所有的功能寫(xiě)到一個(gè)js文件里,效果出來(lái)就行,隨你們?cè)趺春鷶囆U纏

。而自從認(rèn)識(shí)了模塊化開(kāi)發(fā),內(nèi)心不止一次告訴自己,拿到需求bigger一定要高,一定要高(雖然require.js和sea.js這兩個(gè)東東在圈內(nèi)多多少少還是有些爭(zhēng)議)……

廢話少說(shuō),首先來(lái)分析一下需要?jiǎng)澐侄嗌賯€(gè)模塊吧:

1,一開(kāi)始就要有個(gè)入口模塊的吧?恩,必須的! 入口模塊 Get√~

2,既然是拖拽,要有個(gè)拖拽模塊吧?恩,必須的! 拖拽模塊 Get√~

3,既然要縮放,要有個(gè)縮放模塊吧?恩,必須的! 縮放模塊 Get√~

4,既然限定縮放范圍<=500px,那還要有個(gè)限定縮放范圍的模塊吧?恩,這個(gè)可以有,但為了以后調(diào)整范圍數(shù)值方便,還是單列個(gè)模塊吧。 限定縮放范圍模塊 Get√~

到這里我們就把本需求劃分成了四個(gè)模塊:

·  入口模塊:main.js

·  拖拽模塊:drag.js

·  縮放模塊:scale.js

·  限定縮放范圍模塊:range.js

首先,是頁(yè)面引入入口模塊(我盡量把注釋都寫(xiě)在代碼中,以便對(duì)照代碼,這樣也就不用寫(xiě)大片大片的文字了~):

1  <script>2     seajs.use('./js/main.js');//沒(méi)有callback函數(shù)表明引入后直接執(zhí)行入口模塊3 </script>

接下來(lái)看看 入口模塊(main.js) 里都應(yīng)該有些神馬東東吧:

 1 //入口模塊 2 define(function(require,exports,module){ 3     var $id = function(_id){return document.getElementById(_id);} 4     var oInput = $id("button1"); 5     var div1 = $id("div1"); 6     var div2 = $id("div2"); 7     var div3 = $id("div3");//以上是獲取頁(yè)面元素的幾只變量 8     require('./drag.js').drag(div3);//引入拖拽模塊,執(zhí)行拖拽模塊接口中的drag方法并傳參 9     exports.oInput = oInput;10     oInput.onclick = function(){11         div1.style.display = "block";12         require('./scale.js').scale(div1,div2);//引入縮放模塊,執(zhí)行縮放模塊接口中的scale方法并傳參13     }14 });

恩,還真是全面呢

,把拖拽模塊和縮放模塊都引進(jìn)來(lái)了??纯?拖拽模塊(drag.js) 吧~

 1 //拖拽模塊 2 define(function(require,exports,module){ 3     //這個(gè)方法就是實(shí)現(xiàn)拖拽的方法,不用詳述了吧? 4     function drag(obj){ 5         var disX = 0; 6         var disY = 0; 7         obj.onmousedown = function(e){ 8             var e = e || window.event; 9             disX = e.clientX - obj.offsetLeft;10             disY = e.clientY - obj.offsetTop;11             document.onmousemove = function(e){12                 var e = e || window.event;13                 var l = require('./range.js').range(e.clientX - disX, document.documentElement.clientWidth - obj.offsetWidth,0);14                 var t = require('./range.js').range(e.clientY - disY, document.documentElement.clientHeight - obj.offsetHeight,0);15                 obj.style.left = l + "px";16                 obj.style.top = t + "px";17             }18             document.onmouseup = function(){19                 document.onmousemove = null;20                 document.onmouseup = null;21             }22         }23     }24     exports.drag = drag;//返回拖拽模塊中想要被公開(kāi)的對(duì)象,也就是在本模塊中定義的drag方法。注意有參數(shù)~25 });

接下來(lái)是 縮放模塊(scale.js) ??s放模塊還需要調(diào)用  限定縮放范圍模塊 (range.js)  的哦~這點(diǎn)不要搞忘了。

 1 //縮放模塊 2 define(function(require,exports,module){ 3     //這個(gè)方法就是obj2控制obj1改變大小的方法,也不再詳述啦~ 4     function scale(obj1,obj2){ 5         var disX = 0; 6         var disY = 0; 7         var disW = 0; 8         var disH = 0; 9         obj2.onmousedown = function(e){10             var e = e || window.event;11             disX = e.clientX;12             disY = e.clientY;13             disW = obj1.offsetWidth;14             disH = obj1.offsetHeight;15             document.onmousemove = function(e){16                 var e = e || window.event;17                 var w = require('./range.js').range(e.clientX - disX + disW,500,100);//看這里看這里,引入了限定范圍的range.js模塊~18                 var h = require('./range.js').range(e.clientY - disY + disH,500,100);19                 obj1.style.width = w + "px";20                 obj1.style.height = h + "px";21             }22             document.onmouseup = function(){23                 document.onmousemove = null;24                 document.onmouseup = null;25             }26         }27     }28     exports.scale = scale;//將需要公開(kāi)的對(duì)象存入模塊接口中,以便其他模塊調(diào)用~29 });

最后就是 限定范圍的模塊(range.js) 了。

 1 //限定拖拽的范圍模塊 2 define(function(require,exports,module){ 3     function range(inum,imax,imin){ 4         if(inum > imax){ 5             return imax; 6         }else if(inum < imin){ 7             return imin; 8         }else{ 9             return inum;10         }11     }12     exports.range = range;13 });

這就是模塊化,雖然在這個(gè)實(shí)例中我們用到了4個(gè)js,但在頁(yè)面上我們只引入了一個(gè)入口模塊main.js,其他模塊都會(huì)按需自動(dòng)引入(如下圖所示),而且每個(gè)功能模塊的區(qū)分特別清晰,再也不用擔(dān)心神馬命名沖突啊、依賴混亂啊之類的,而且團(tuán)隊(duì)小伙伴每人負(fù)責(zé)一個(gè)模塊,只要放出當(dāng)前模塊的公開(kāi)接口并提供簡(jiǎn)要的說(shuō)明文檔(因?yàn)闃?biāo)準(zhǔn)統(tǒng)一),其他小伙伴們寫(xiě)的模塊就能非常方便地調(diào)用到你寫(xiě)的模塊,連修改的時(shí)候都不用考慮對(duì)其他功能的影響,變得更大膽了呢~

查看完整DEMO請(qǐng)猛戳

寫(xiě)在最后

其實(shí)本文介紹的模塊化和seajs的使用依舊比較淺顯,但基本的模塊化思想已經(jīng)融入到例子中了。 如果你經(jīng)歷過(guò)前文所述的以前寫(xiě)js邏輯的各種糾結(jié)各種坑爹,不妨嘗試一下將你的代碼模塊化,那將是一種飛一樣的感覺(jué)……

本文最后會(huì)為大家列出一些相關(guān)的資料,想深入了解的小伙伴們可以果斷收走~

SeaJs官網(wǎng) :  http://seajs.org/docs/

CMD 模塊定義規(guī)范: https://github.com/seajs/seajs/issues/242

玉伯:AMD和CMD的區(qū)別: http://www.zhihu.com/question/20351507/answer/14859415

AMD and CMD are dead之js模塊化黑魔法 :  http://www.cnblogs.com/iamzhanglei/p/3790346.html

(后續(xù)會(huì)繼續(xù)補(bǔ)充……)

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
詳解JavaScript模塊化開(kāi)發(fā)
seajs實(shí)戰(zhàn)參考
CommonJS,AMD,CMD區(qū)別
一步步學(xué)會(huì)使用SeaJS 2.0
前端模塊化開(kāi)發(fā)(AMD和CDM規(guī)范)
Javascript模塊化編程(三):模塊化編程實(shí)戰(zhàn),試用SeaJS
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服