新聞中心
【稿件】前言
在JavaScript發(fā)展初期就是為了實(shí)現(xiàn)簡(jiǎn)單的頁(yè)面交互邏輯,寥寥數(shù)語(yǔ)即可;如今CPU、瀏覽器性能得到了極大的提升,很多頁(yè)面邏輯遷移到了客戶端(表單驗(yàn)證等),隨著web2.0時(shí)代的到來(lái),Ajax技術(shù)得到廣泛應(yīng)用,jQuery等前端庫(kù)層出不窮,前端代碼日益膨脹,此時(shí)在JS方面就會(huì)考慮使用模塊化規(guī)范去管理。

我們提供的服務(wù)有:成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、吉首ssl等。為數(shù)千家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的吉首網(wǎng)站制作公司
本文內(nèi)容主要有理解模塊化,為什么要模塊化,模塊化的優(yōu)缺點(diǎn)以及模塊化規(guī)范,并且介紹下開發(fā)中***的CommonJS, AMD, ES6、CMD規(guī)范。本文試圖站在小白的角度,用通俗易懂的筆調(diào)介紹這些枯燥無(wú)味的概念,希望諸君閱讀后,對(duì)模塊化編程有個(gè)全新的認(rèn)識(shí)和理解!
如需本文的源代碼,請(qǐng)猛戳源代碼 。
一、模塊化的理解
1.什么是模塊?
- 將一個(gè)復(fù)雜的程序依據(jù)一定的規(guī)則(規(guī)范)封裝成幾個(gè)塊(文件), 并進(jìn)行組合在一起
- 塊的內(nèi)部數(shù)據(jù)與實(shí)現(xiàn)是私有的, 只是向外部暴露一些接口(方法)與外部其它模塊通信
2.模塊化的進(jìn)化過(guò)程
- 全局function模式 : 將不同的功能封裝成不同的全局函數(shù)
- 編碼: 將不同的功能封裝成不同的全局函數(shù)
- 問(wèn)題: 污染全局命名空間, 容易引起命名沖突或數(shù)據(jù)不安全,而且模塊成員之間看不出直接關(guān)系
- function m1(){
- //...
- }
- function m2(){
- //...
- }
- namespace模式 : 簡(jiǎn)單對(duì)象封裝
- 作用: 減少了全局變量,解決命名沖突
- 問(wèn)題: 數(shù)據(jù)不安全(外部可以直接修改模塊內(nèi)部的數(shù)據(jù))
- let myModule = {
- data: 'www.baidu.com',
- foo() {
- console.log(`foo() ${this.data}`)
- },
- bar() {
- console.log(`bar() ${this.data}`)
- }
- }
- myModule.data = 'other data' //能直接修改模塊內(nèi)部的數(shù)據(jù)
- myModule.foo() // foo() other data
這樣的寫法會(huì)暴露所有模塊成員,內(nèi)部狀態(tài)可以被外部改寫。
- IIFE模式:匿名函數(shù)自調(diào)用(閉包)
- 作用: 數(shù)據(jù)是私有的, 外部只能通過(guò)暴露的方法操作
- 編碼: 將數(shù)據(jù)和行為封裝到一個(gè)函數(shù)內(nèi)部, 通過(guò)給window添加屬性來(lái)向外暴露接口
- 問(wèn)題: 如果當(dāng)前這個(gè)模塊依賴另一個(gè)模塊怎么辦?
- // index.html文件
- // module.js文件
- (function(window) {
- let data = 'www.baidu.com'
- //操作數(shù)據(jù)的函數(shù)
- function foo() {
- //用于暴露有函數(shù)
- console.log(`foo() ${data}`)
- }
- function bar() {
- //用于暴露有函數(shù)
- console.log(`bar() ${data}`)
- otherFun() //內(nèi)部調(diào)用
- }
- function otherFun() {
- //內(nèi)部私有的函數(shù)
- console.log('otherFun()')
- }
- //暴露行為
- window.myModule = { foo, bar } //ES6寫法
- })(window)
***得到的結(jié)果:
- IIFE模式增強(qiáng) : 引入依賴
這就是現(xiàn)代模塊實(shí)現(xiàn)的基石。
- // module.js文件
- (function(window, $) {
- let data = 'www.baidu.com'
- //操作數(shù)據(jù)的函數(shù)
- function foo() {
- //用于暴露有函數(shù)
- console.log(`foo() ${data}`)
- $('body').css('background', 'red')
- }
- function bar() {
- //用于暴露有函數(shù)
- console.log(`bar() ${data}`)
- otherFun() //內(nèi)部調(diào)用
- }
- function otherFun() {
- //內(nèi)部私有的函數(shù)
- console.log('otherFun()')
- }
- //暴露行為
- window.myModule = { foo, bar }
- })(window, jQuery)
- // index.html文件
上例子通過(guò)jquery方法將頁(yè)面的背景顏色改成紅色,所以必須先引入jQuery庫(kù),就把這個(gè)庫(kù)當(dāng)作參數(shù)傳入。這樣做除了保證模塊的獨(dú)立性,還使得模塊之間的依賴關(guān)系變得明顯。
3. 模塊化的好處
- 避免命名沖突(減少命名空間污染)
- 更好的分離, 按需加載
- 更高復(fù)用性
- 高可維護(hù)性
4. 引入 ***得到如下結(jié)果: 這種方式缺點(diǎn)很明顯:首先會(huì)發(fā)送多個(gè)請(qǐng)求,其次引入的js文件順序不能搞錯(cuò),否則會(huì)報(bào)錯(cuò)! RequireJS是一個(gè)工具庫(kù),主要用于客戶端的模塊管理。它的模塊管理遵守AMD規(guī)范,RequireJS的基本思想是,通過(guò)define方法,將代碼定義為模塊;通過(guò)require方法,實(shí)現(xiàn)代碼的模塊加載。 接下來(lái)介紹AMD規(guī)范在瀏覽器實(shí)現(xiàn)的步驟: ①下載require.js, 并引入 然后將require.js導(dǎo)入項(xiàng)目: js/libs/require.js ②創(chuàng)建項(xiàng)目結(jié)構(gòu) ③定義require.js的模塊代碼 ④頁(yè)面引入require.js模塊: 在index.html引入 此外在項(xiàng)目中如何引入第三方庫(kù)?只需在上面代碼的基礎(chǔ)稍作修改: 上例是在alerter.js文件中引入jQuery第三方庫(kù),main.js文件也要有相應(yīng)的路徑配置。 小結(jié):通過(guò)兩者的比較,可以得出AMD模塊定義的方法非常清晰,不會(huì)污染全局環(huán)境,能夠清楚地顯示依賴關(guān)系。AMD模式可以用于瀏覽器環(huán)境,并且允許非同步加載模塊,也可以根據(jù)需要?jiǎng)討B(tài)加載模塊。 3.CMD CMD規(guī)范專門用于瀏覽器端,模塊的加載是異步的,模塊使用時(shí)才會(huì)加載執(zhí)行。CMD規(guī)范整合了CommonJS和AMD規(guī)范的特點(diǎn)。在 Sea.js 中,所有 JavaScript 模塊都遵循 CMD模塊定義規(guī)范。 (1)CMD規(guī)范基本語(yǔ)法 定義暴露模塊: 引入使用模塊: (2)sea.js簡(jiǎn)單使用教程 ①下載sea.js, 并引入 然后將sea.js導(dǎo)入項(xiàng)目: js/libs/sea.js ②創(chuàng)建項(xiàng)目結(jié)構(gòu) ③定義sea.js的模塊代碼 ④在index.html中引入 ***得到結(jié)果如下: 4.ES6模塊化 ES6 模塊的設(shè)計(jì)思想是盡量的靜態(tài)化,使得編譯時(shí)就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運(yùn)行時(shí)確定這些東西。比如,CommonJS 模塊就是對(duì)象,輸入時(shí)必須查找對(duì)象屬性。 (1)ES6模塊化語(yǔ)法 export命令用于規(guī)定模塊的對(duì)外接口,import命令用于輸入其他模塊提供的功能。 如上例所示,使用import命令的時(shí)候,用戶需要知道所要加載的變量名或函數(shù)名,否則無(wú)法加載。為了給用戶提供方便,讓他們不用閱讀文檔就能加載模塊,就要用到export default命令,為模塊指定默認(rèn)輸出。 模塊默認(rèn)輸出, 其他模塊加載該模塊時(shí),import命令可以為該匿名函數(shù)指定任意名字。 (2)ES6 模塊與 CommonJS 模塊的差異 它們有兩個(gè)重大差異: ① CommonJS 模塊輸出的是一個(gè)值的拷貝,ES6 模塊輸出的是值的引用。 ② CommonJS 模塊是運(yùn)行時(shí)加載,ES6 模塊是編譯時(shí)輸出接口。 第二個(gè)差異是因?yàn)?CommonJS 加載的是一個(gè)對(duì)象(即module.exports屬性),該對(duì)象只有在腳本運(yùn)行完才會(huì)生成。而 ES6 模塊不是對(duì)象,它的對(duì)外接口只是一種靜態(tài)定義,在代碼靜態(tài)解析階段就會(huì)生成。 下面重點(diǎn)解釋***個(gè)差異,我們還是舉上面那個(gè)CommonJS模塊的加載機(jī)制例子: ES6 模塊的運(yùn)行機(jī)制與 CommonJS 不一樣。ES6 模塊是動(dòng)態(tài)引用,并且不會(huì)緩存值,模塊里面的變量綁定其所在的模塊。 (3) ES6-Babel-Browserify使用教程 簡(jiǎn)單來(lái)說(shuō)就一句話:使用Babel將ES6編譯為ES5代碼,使用Browserify編譯打包js。 ①定義package.json文件 ②安裝babel-cli, babel-preset-es2015和browserify ③定義.babelrc文件 ④定義模塊代碼 ⑤ 編譯并在index.html中引入 然后在index.html文件中引入: ***得到如下結(jié)果: 此外第三方庫(kù)(以jQuery為例)如何引入呢? 首先安裝依賴npm install jquery@1 然后在app.js文件中引入: 作者:浪里行舟,慕課網(wǎng)認(rèn)證作者,前端愛好者,立志往全棧工程師發(fā)展,從事前端一年多,目前技術(shù)棧有vue全家桶、ES6以及l(fā)ess等,樂(lè)于分享,最近一年寫了五六十篇原創(chuàng)技術(shù)文章,得到諸多好評(píng)! 【原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文作者和出處為.com】
三、總結(jié)
參考文章
文章題目:僅需一篇,搞定前端模塊化
文章分享:http://www.dlmjj.cn/article/dpscijc.html


咨詢
建站咨詢
