溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

分析web前端模塊化開發(fā)

發(fā)布時(shí)間:2021-11-06 16:00:05 來源:億速云 閱讀:132 作者:iii 欄目:web開發(fā)

這篇文章主要介紹“分析web前端模塊化開發(fā)”,在日常操作中,相信很多人在分析web前端模塊化開發(fā)問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”分析web前端模塊化開發(fā)”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

  1. 命名沖突

  首先從一個(gè)簡單的習(xí)慣開始。

  由于以前一直做 JavaEE 開發(fā)的緣故,在 JavaScript 開發(fā)中,我已經(jīng)習(xí)慣將項(xiàng)目中的一些通用功能抽象出來,形成一個(gè)個(gè)的獨(dú)立函數(shù),以便于實(shí)現(xiàn)代碼復(fù)用,如:

  function css(element, attr) { // 獲取 element 元素的 attr 對應(yīng)的 CSS 屬性值

  // ...

  }

  function offset(element) { // 獲取 element 元素在文檔中的位置坐標(biāo)

  // ...

  }

  并把這些封裝的函數(shù)放在統(tǒng)一的 tools.js 文件中。

  如果頁面功能實(shí)現(xiàn)需要使用到這些函數(shù),則直接通過 引入即可。

  前期感覺一切都好,大家也都覺得寫這樣的工具文件對開發(fā)來說很方便,直到使用越來越多,頁面功能越來越復(fù)雜,大家要實(shí)現(xiàn)的需求也越來越多樣。

  這時(shí)有人就抱怨,因?yàn)橐肓? tools.js 文件,如果要定義一個(gè)能夠設(shè)置 css 屬性值的函數(shù),那么就只有取另外的函數(shù)名稱(如 setCss )而不能再使用 css 這個(gè)函數(shù)名稱了,同樣如果要設(shè)置一個(gè)元素在整個(gè)文檔中的定位坐標(biāo),也不能再使用 offset 這個(gè)函數(shù)名稱,因?yàn)槟菢拥脑?,就與 tools.js 文件中已定義的函數(shù)名稱沖突了。

  既然問題出現(xiàn)了,就需要解決。

  在 Java 中有一個(gè)非常實(shí)用的技術(shù)——package,它將邏輯上相關(guān)的代碼組織在一起使用“包”來進(jìn)行管理,這相當(dāng)于文件系統(tǒng)中的文件夾。在文件系統(tǒng)中,文件夾內(nèi)是相對獨(dú)立的一個(gè)空間,不用擔(dān)心一個(gè)文件夾和另一個(gè)文件夾中文件命名的沖突。在“包”中也一樣,可以解決文件命名沖突問題,如果要在包外部再使用到包內(nèi)的資源,直接通過 import 導(dǎo)入相關(guān)的 package 即可。類似包這樣的概念,在其它的語言(如 C#)中也稱為命名空間。

  JavaScript 中并沒有提供原生的包或命名空間的支持,但可以使用其它的方法(如對象、閉包)來實(shí)現(xiàn)類似的效果。

  參照 Java 的方式,我使用 JavaScript 中的對象來簡單修改 tools.js 文件:

  var Util = {

  css : function(element, attr) {

  // ...

  },

  offset : function(element) {

  // ...

  }

  };

  這樣,當(dāng)引入 tools.js 文件后,要獲取 CSS 樣式或獲取元素的文檔坐標(biāo),就通過類似 Util.css()/Util.offset() 的方法來實(shí)現(xiàn)。css 與 offset 的作用域是在對象 Util 下,再全局或是新對象中定義 css 屬性是不受影響的。

  Util 這個(gè)名稱也具有通用性,通常用作輔助工具定義的時(shí)候會(huì)使用到這個(gè)名稱,為了體現(xiàn)該名稱的唯一性,可以繼續(xù)借鑒 Java 中 package 的命名規(guī)范(域名倒置):

  var com = {};

  com.github = {};

  com.github.itrainhub = {};

  com.github.itrainhub.Util = {

  css : function(element, attr) {

  // ...

  },

  offset : function(element) {

  // ...

  }

  };

  要獲取 CSS 樣式值,則可使用 com.github.itrainhub.Util.css() 方法。但這樣的寫法增加了記憶難度,YUI 中關(guān)于這一點(diǎn)有比較好的解決方案,先按下暫且不表。

  使用對象的寫法可解決命名沖突問題,但這種寫法也會(huì)暴露對象的所有成員,使對象內(nèi)部狀態(tài)可以在對象外部被改寫。比如在對象內(nèi)部存在計(jì)數(shù)器:

  var Util = {

  _count : 0

  }

  在對象外部可以通過 Util._count = 18; 修改該計(jì)數(shù)器的值,這是不安全的。

  像計(jì)數(shù)器這樣的變量,通常可能是作為對象的私有成員存在,不希望在對象外部還能繼續(xù)修改其值,這時(shí),可以使用 IIFE(立即執(zhí)行函數(shù))來設(shè)計(jì):

  var Util = (function(){

  var _count = 0;

  function _css(element, attr) {

  // ...

  }

  function _offset(element) {

  // ...

  }

  return {

  css : _css,

  offset : _offset

  }

  })();

  這樣,在外部就不能再直接修改 _count 的值了。

  通過命名空間,的確可以解決命名沖突的問題,我們可以暫時(shí)松一口氣了。

  2. 文件依賴

  接著 tools.js 繼續(xù)開發(fā)。

  在 tools.js 的基礎(chǔ)上,可以開發(fā)出一些 UI 層通用的組件,如放大鏡、輪播圖之類的,這樣各個(gè)項(xiàng)目中要使用這些功能的時(shí)候就不用重復(fù)造輪子了。

  通常情況下,每個(gè) UI 組件都是以獨(dú)立的 js 文件存在的,比如放大鏡,可以將它放到一個(gè) zoom.js 的文件中,當(dāng)要使用到放大鏡組件時(shí),通過 引入即可。

  但很多時(shí)候,在使用 zoom.js 之前忘記了引入 tools.js,則使用 zoom.js 就會(huì)報(bào)錯(cuò),無法保證它的正常執(zhí)行。

  zoom.js 的正常執(zhí)行依賴于 tools.js 的使用,上述的問題都還是比較容易解決的,但隨著團(tuán)隊(duì)越來越大,業(yè)務(wù)需求越來越復(fù)雜,項(xiàng)目中組件間的依賴關(guān)系也會(huì)變得越來越復(fù)雜。比如:

  某一天,我擴(kuò)充了 zoom.js 組件的功能,但除了使用到 tools.js 外,還使用到另一個(gè)工具 js 組件:helper.js。如果項(xiàng)目中已有 N 個(gè)地方之前使用到了 zoom.js 組件,我就只好全局搜索每個(gè)引用 zoom.js 的地方,再加上對 helper.js 的引用。

  再想想,隨著項(xiàng)目推進(jìn),我們會(huì)繼續(xù)修改 tools.js,添加更多的組件 component_1.js、component_2.js……某些組件中只使用到 tools.js,某些只使用到 helper.js,而某些組件既使用到了 tools.js 又使用到了 helper.js。那么關(guān)于組件間依賴關(guān)系的維護(hù),工作量可想而知,如果以人肉的方式來保證依賴關(guān)系的維護(hù),簡直就要崩潰掉了。

  為什么維護(hù)組件間的依賴關(guān)系這么費(fèi)神呢,因?yàn)? JavaScript 中天生缺少了引入其它 js 文件的語法。在 Java 中可以通過 import 引入依賴組件,在 CSS 中也有 @import 命令去引入其它的 CSS 文件,而 js 中卻不能自動(dòng)管理依賴。

  除了文件間的依賴關(guān)系維護(hù)不便外,如果在頁面中引入的組件非常多,我們還得保證引用組件的路徑及先后順序不能出錯(cuò),一旦出錯(cuò),又得花時(shí)間查找錯(cuò)誤,可想而知工作量是很可觀了,再加上組件引入過多,又是以同步的方式加載各組件,也可能導(dǎo)致瀏覽器假死的現(xiàn)象。

  要解決這些問題,模塊化開發(fā)的價(jià)值就體現(xiàn)出來了。

  3. 模塊化開發(fā)

  3.1 模塊化

  所謂模塊化,就是把一個(gè)相對獨(dú)立的功能,單獨(dú)形成一個(gè)文件,可輸入指定依賴、輸出指定的函數(shù),供外界調(diào)用,其它都在內(nèi)部隱藏實(shí)現(xiàn)細(xì)節(jié)。這樣即可方便不同的項(xiàng)目重復(fù)使用,也不會(huì)對項(xiàng)目造成額外的影響。

  前端使用模塊化載發(fā)主要的作用是:

  ? 異步加載 js,避免瀏覽器假死

  ? 管理模塊間依賴關(guān)系,便于模塊的維護(hù)

  有了模塊,我們就可以更方便地使用別人的代碼,想要什么功能,就加載什么模塊。

  但要使用模塊的前提,是必然要形成可遵循的開發(fā)規(guī)范,使得開發(fā)者和使用者都有據(jù)可尋,否則你有你的寫法,我有我的寫法,大家沒辦法統(tǒng)一,也就不能很好的互用了。

  目前通用的規(guī)范是,服務(wù)器端使用 CommonJS 規(guī)范,客戶端使用 AMD/CMD 規(guī)范。

  3.2 CommonJS

  CommonJS 規(guī)范出現(xiàn)是在 2009 年,Node.js 就是該規(guī)范的實(shí)現(xiàn)。CommonJS 規(guī)范中是這樣加載模塊的:

  var gulp = require("gulp");

  gulp.task(/* 任務(wù) */);

  模塊的加載是同步的,這種寫法適合服務(wù)器端,因?yàn)樵诜?wù)器讀取的模塊都是在本地磁盤,加載速度很快,可同步加載完成。但是如果在客戶端瀏覽器中,因?yàn)槟K是放在服務(wù)器端的,模塊加載取決于網(wǎng)絡(luò)環(huán)境,以同步的方式加載模塊時(shí)有可能出現(xiàn)“假死”狀況。

  今天我主要介紹針對瀏覽器編程,不針對 Node.js 內(nèi)容,所以在此關(guān)于 CommonJS 規(guī)范就不作深究,知道 require() 用于加載模塊即可。

  3.3 AMD

  由于在瀏覽器端,模塊使用同步方式加載可能出現(xiàn)假死,那么我們采用異步加載的方式來實(shí)現(xiàn)模塊加載,這就誕生了 AMD 的規(guī)范。

  AMD 即 Asynchronous Module Definition 的簡稱,表示“異步模塊定義”的意思。AMD 規(guī)范:https://github.com/amdjs/amdjs-api/wiki/AMD。

  AMD 采用異步方式加載模塊,模塊的加載不影響它后面語句的運(yùn)行。所有依賴所加載模塊的語句,都被定義在一個(gè)回調(diào)函數(shù)中,等到模塊加載完畢后,回調(diào)函數(shù)才會(huì)執(zhí)行。

  AMD 也采用 require() 來加載模塊,語法結(jié)構(gòu)為:

  require([module], callback);

  module 是數(shù)組參數(shù),表示所加載模塊的名稱;callback 是回調(diào)函數(shù)參數(shù),所有模塊加載完畢后執(zhí)行該回調(diào)函數(shù)。如:

  require(["jquery"], function($){

  $("#box").text("test");

  });

  3.4 CMD

  CMD 即 Common Module Definition 的簡稱,表示“通用模塊定義”的意思。CMD 規(guī)范:https://github.com/cmdjs/specification/blob/master/draft/module.md。

  CMD 規(guī)范明確了模塊的基本書寫格式和基本交互規(guī)則,該規(guī)范是在國內(nèi)發(fā)展出來的,由玉伯在推廣 SeaJS 過程中規(guī)范產(chǎn)出的。

  SeaJS 實(shí)現(xiàn)了 CMD 規(guī)范。SeaJS 要解決的問題和 RequireJS 一樣,只不過在模塊定義方式和模塊加載(運(yùn)行、解析)時(shí)機(jī)上有所不同。

  3.5 AMD 與 CMD 的區(qū)別

  AMD 是 RequireJS 在推廣過程中對模塊定義的規(guī)范化產(chǎn)出。

  CMD 是 SeaJS 在推廣過程中對模塊定義的規(guī)范化產(chǎn)出。

  二者主要區(qū)別如下:

  1 對于依賴的模塊,AMD 是提前執(zhí)行,CMD 是延遲執(zhí)行。

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

  3 AMD 的 API 默認(rèn)是一個(gè)當(dāng)多個(gè)用,CMD 的 API 嚴(yán)格區(qū)分,推崇職責(zé)單一。

  當(dāng)然還有一些其它細(xì)節(jié)上的區(qū)別,具體看規(guī)范的定義就好。

到此,關(guān)于“分析web前端模塊化開發(fā)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

web
AI