您好,登錄后才能下訂單哦!
這篇文章主要介紹“分析web前端模塊化開發”,在日常操作中,相信很多人在分析web前端模塊化開發問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”分析web前端模塊化開發”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
1. 命名沖突
首先從一個簡單的習慣開始。
由于以前一直做 JavaEE 開發的緣故,在 JavaScript 開發中,我已經習慣將項目中的一些通用功能抽象出來,形成一個個的獨立函數,以便于實現代碼復用,如:
function css(element, attr) { // 獲取 element 元素的 attr 對應的 CSS 屬性值
// ...
}
function offset(element) { // 獲取 element 元素在文檔中的位置坐標
// ...
}
并把這些封裝的函數放在統一的 tools.js 文件中。
如果頁面功能實現需要使用到這些函數,則直接通過 引入即可。
前期感覺一切都好,大家也都覺得寫這樣的工具文件對開發來說很方便,直到使用越來越多,頁面功能越來越復雜,大家要實現的需求也越來越多樣。
這時有人就抱怨,因為引入了 tools.js 文件,如果要定義一個能夠設置 css 屬性值的函數,那么就只有取另外的函數名稱(如 setCss )而不能再使用 css 這個函數名稱了,同樣如果要設置一個元素在整個文檔中的定位坐標,也不能再使用 offset 這個函數名稱,因為那樣的話,就與 tools.js 文件中已定義的函數名稱沖突了。
既然問題出現了,就需要解決。
在 Java 中有一個非常實用的技術——package,它將邏輯上相關的代碼組織在一起使用“包”來進行管理,這相當于文件系統中的文件夾。在文件系統中,文件夾內是相對獨立的一個空間,不用擔心一個文件夾和另一個文件夾中文件命名的沖突。在“包”中也一樣,可以解決文件命名沖突問題,如果要在包外部再使用到包內的資源,直接通過 import 導入相關的 package 即可。類似包這樣的概念,在其它的語言(如 C#)中也稱為命名空間。
JavaScript 中并沒有提供原生的包或命名空間的支持,但可以使用其它的方法(如對象、閉包)來實現類似的效果。
參照 Java 的方式,我使用 JavaScript 中的對象來簡單修改 tools.js 文件:
var Util = {
css : function(element, attr) {
// ...
},
offset : function(element) {
// ...
}
};
這樣,當引入 tools.js 文件后,要獲取 CSS 樣式或獲取元素的文檔坐標,就通過類似 Util.css()/Util.offset() 的方法來實現。css 與 offset 的作用域是在對象 Util 下,再全局或是新對象中定義 css 屬性是不受影響的。
Util 這個名稱也具有通用性,通常用作輔助工具定義的時候會使用到這個名稱,為了體現該名稱的唯一性,可以繼續借鑒 Java 中 package 的命名規范(域名倒置):
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 中關于這一點有比較好的解決方案,先按下暫且不表。
使用對象的寫法可解決命名沖突問題,但這種寫法也會暴露對象的所有成員,使對象內部狀態可以在對象外部被改寫。比如在對象內部存在計數器:
var Util = {
_count : 0
}
在對象外部可以通過 Util._count = 18; 修改該計數器的值,這是不安全的。
像計數器這樣的變量,通常可能是作為對象的私有成員存在,不希望在對象外部還能繼續修改其值,這時,可以使用 IIFE(立即執行函數)來設計:
var Util = (function(){
var _count = 0;
function _css(element, attr) {
// ...
}
function _offset(element) {
// ...
}
return {
css : _css,
offset : _offset
}
})();
這樣,在外部就不能再直接修改 _count 的值了。
通過命名空間,的確可以解決命名沖突的問題,我們可以暫時松一口氣了。
2. 文件依賴
接著 tools.js 繼續開發。
在 tools.js 的基礎上,可以開發出一些 UI 層通用的組件,如放大鏡、輪播圖之類的,這樣各個項目中要使用這些功能的時候就不用重復造輪子了。
通常情況下,每個 UI 組件都是以獨立的 js 文件存在的,比如放大鏡,可以將它放到一個 zoom.js 的文件中,當要使用到放大鏡組件時,通過 引入即可。
但很多時候,在使用 zoom.js 之前忘記了引入 tools.js,則使用 zoom.js 就會報錯,無法保證它的正常執行。
zoom.js 的正常執行依賴于 tools.js 的使用,上述的問題都還是比較容易解決的,但隨著團隊越來越大,業務需求越來越復雜,項目中組件間的依賴關系也會變得越來越復雜。比如:
某一天,我擴充了 zoom.js 組件的功能,但除了使用到 tools.js 外,還使用到另一個工具 js 組件:helper.js。如果項目中已有 N 個地方之前使用到了 zoom.js 組件,我就只好全局搜索每個引用 zoom.js 的地方,再加上對 helper.js 的引用。
再想想,隨著項目推進,我們會繼續修改 tools.js,添加更多的組件 component_1.js、component_2.js……某些組件中只使用到 tools.js,某些只使用到 helper.js,而某些組件既使用到了 tools.js 又使用到了 helper.js。那么關于組件間依賴關系的維護,工作量可想而知,如果以人肉的方式來保證依賴關系的維護,簡直就要崩潰掉了。
為什么維護組件間的依賴關系這么費神呢,因為 JavaScript 中天生缺少了引入其它 js 文件的語法。在 Java 中可以通過 import 引入依賴組件,在 CSS 中也有 @import 命令去引入其它的 CSS 文件,而 js 中卻不能自動管理依賴。
除了文件間的依賴關系維護不便外,如果在頁面中引入的組件非常多,我們還得保證引用組件的路徑及先后順序不能出錯,一旦出錯,又得花時間查找錯誤,可想而知工作量是很可觀了,再加上組件引入過多,又是以同步的方式加載各組件,也可能導致瀏覽器假死的現象。
要解決這些問題,模塊化開發的價值就體現出來了。
3. 模塊化開發
3.1 模塊化
所謂模塊化,就是把一個相對獨立的功能,單獨形成一個文件,可輸入指定依賴、輸出指定的函數,供外界調用,其它都在內部隱藏實現細節。這樣即可方便不同的項目重復使用,也不會對項目造成額外的影響。
前端使用模塊化載發主要的作用是:
? 異步加載 js,避免瀏覽器假死
? 管理模塊間依賴關系,便于模塊的維護
有了模塊,我們就可以更方便地使用別人的代碼,想要什么功能,就加載什么模塊。
但要使用模塊的前提,是必然要形成可遵循的開發規范,使得開發者和使用者都有據可尋,否則你有你的寫法,我有我的寫法,大家沒辦法統一,也就不能很好的互用了。
目前通用的規范是,服務器端使用 CommonJS 規范,客戶端使用 AMD/CMD 規范。
3.2 CommonJS
CommonJS 規范出現是在 2009 年,Node.js 就是該規范的實現。CommonJS 規范中是這樣加載模塊的:
var gulp = require("gulp");
gulp.task(/* 任務 */);
模塊的加載是同步的,這種寫法適合服務器端,因為在服務器讀取的模塊都是在本地磁盤,加載速度很快,可同步加載完成。但是如果在客戶端瀏覽器中,因為模塊是放在服務器端的,模塊加載取決于網絡環境,以同步的方式加載模塊時有可能出現“假死”狀況。
今天我主要介紹針對瀏覽器編程,不針對 Node.js 內容,所以在此關于 CommonJS 規范就不作深究,知道 require() 用于加載模塊即可。
3.3 AMD
由于在瀏覽器端,模塊使用同步方式加載可能出現假死,那么我們采用異步加載的方式來實現模塊加載,這就誕生了 AMD 的規范。
AMD 即 Asynchronous Module Definition 的簡稱,表示“異步模塊定義”的意思。AMD 規范:https://github.com/amdjs/amdjs-api/wiki/AMD。
AMD 采用異步方式加載模塊,模塊的加載不影響它后面語句的運行。所有依賴所加載模塊的語句,都被定義在一個回調函數中,等到模塊加載完畢后,回調函數才會執行。
AMD 也采用 require() 來加載模塊,語法結構為:
require([module], callback);
module 是數組參數,表示所加載模塊的名稱;callback 是回調函數參數,所有模塊加載完畢后執行該回調函數。如:
require(["jquery"], function($){
$("#box").text("test");
});
3.4 CMD
CMD 即 Common Module Definition 的簡稱,表示“通用模塊定義”的意思。CMD 規范:https://github.com/cmdjs/specification/blob/master/draft/module.md。
CMD 規范明確了模塊的基本書寫格式和基本交互規則,該規范是在國內發展出來的,由玉伯在推廣 SeaJS 過程中規范產出的。
SeaJS 實現了 CMD 規范。SeaJS 要解決的問題和 RequireJS 一樣,只不過在模塊定義方式和模塊加載(運行、解析)時機上有所不同。
3.5 AMD 與 CMD 的區別
AMD 是 RequireJS 在推廣過程中對模塊定義的規范化產出。
CMD 是 SeaJS 在推廣過程中對模塊定義的規范化產出。
二者主要區別如下:
1 對于依賴的模塊,AMD 是提前執行,CMD 是延遲執行。
2 CMD 推崇依賴就近,AMD 推崇依賴前置。
3 AMD 的 API 默認是一個當多個用,CMD 的 API 嚴格區分,推崇職責單一。
當然還有一些其它細節上的區別,具體看規范的定義就好。
到此,關于“分析web前端模塊化開發”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。