目錄
什麼是模組化開發?
AMD規格
define() 函數
模組名稱的格式
使用require 和exports
CommonJS規範
RequireJS和SeaJS
為什麼要用requireJS
AMD和CMD
sea.js如何使用?
sea.js 开发实例
A同事
B同事
C同事
D同事
requirejs开发实例
main.js文件
define 模块
main.js引入模块方法
没有依赖
首頁 web前端 js教程 詳解JavaScript模組化開發

詳解JavaScript模組化開發

Feb 21, 2017 am 11:57 AM
javascript 開發 模組化



什麼是模組化開發?

前端開發中,起初只要在script標籤中嵌入幾十上百行程式碼就能實現一些基本的互動效果,後來js被重視,應用程式也廣泛起來了,jQuery,Ajax,Node.Js ,MVC,MVVM等的助力也使得前端開發得到重視,也使得前端專案越來越複雜,然而,JavaScript卻沒有為組織程式碼提供任何明顯幫助,甚至沒有類別的概念,更不用說模組(module)了,那什麼是模組呢?

一個模組就是實現特定功能的文件,有了模組,我們就可以更方便地使用別人的程式碼,想要什麼功能,就載入什麼模組。模組開發需要遵循一定的規範,否則就都亂了套。

根據AMD規範,我們可以使用define定義模組,使用require呼叫模組。

目前,通行的js模組規格主要有兩種:CommonJS和AMD。

AMD規格

AMD 即Asynchronous Module Definition,中文名是「非同步模組定義」的意思。它是一個在瀏覽器端模組化開發的規範,伺服器端的規範是CommonJS

模組將會被非同步加載,模組載入不影響後面語句的運作。所有依賴某些模組的語句均放置在回調函數中。

AMD 是 RequireJS 在推廣過程中對模組定義的規範化的產出。

define() 函數

AMD規格只定義了一個函數 define,它是全域變數。函數的描述為:

define(id?, dependencies?, factory);
登入後複製

參數說明:

id:指定义中模块的名字,可选;如果没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字。如果提供了该参数,模块名必须是“顶级”的和绝对的(不允许相对名字)。

依赖dependencies:是一个当前模块依赖的,已被模块定义的模块标识的数组字面量。
依赖参数是可选的,如果忽略此参数,它应该默认为["require", "exports", "module"]。然而,如果工厂方法的长度属性小于3,加载器会选择以函数的长度属性指定的参数个数调用工厂方法。

工厂方法factory,模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值。
登入後複製

模組名稱的格式

模組名稱用來唯一識別定義中模組,它們同樣在依賴性數組中使用:

模块名是用正斜杠分割的有意义单词的字符串
单词须为驼峰形式,或者".",".."
模块名不允许文件扩展名的形式,如“.js”
模块名可以为 "相对的" 或 "顶级的"。如果首字符为“.”或“..”则为相对的模块名
顶级的模块名从根命名空间的概念模块解析
相对的模块名从 "require" 书写和调用的模块解析
登入後複製

使用require 和exports

建立一個名為"alpha"的模組,使用了require,exports,和名為"beta"的模組:

 define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
       exports.verb = function() {
           return beta.verb();
           //Or:
           return require("beta").verb();
       }
   });
登入後複製

require API 介紹:http://www.php.cn/

AMD規格中文版:http://www.php.cn/(%E4%B8%AD%E6 %96%87%E7%89%88)

目前,實作AMD的函式庫有RequireJS 、curl 、Dojo 、Nodules 等。

CommonJS規範

CommonJS是伺服器端模組的規範,Node.js採用了這個規範。 Node.JS首先採用了js模組化的概念。

根據CommonJS規範,一個單獨的檔案就是一個模組。每一個模組都是一個單獨的作用域,也就是說,在該模組內部定義的變量,無法被其他模組讀取,除非定義為global物件的屬性。

輸出模組變數的最佳方法是使用module.exports物件。

var i = 1;
var max = 30;

module.exports = function () {
  for (i -= 1; i++ < max; ) {
    console.log(i);
  }
  max *= 1.1;
};
登入後複製

上面程式碼透過module.exports對象,定義了一個函數,該函數就是模組外部與內部通訊的橋樑。

載入模組使用require方法,該方法讀取一個檔案並執行,最後傳回檔案內部的module.exports物件。

CommonJS 規格:http://www.php.cn/

RequireJS和SeaJS

RequireJS由James Burke創建,他也是AMD規範的創始人。

define方法用來定義模組,RequireJS要求每個模組放在單獨的檔案裡。

RequireJS 和 Sea.js 都是模組載入器,倡導模組化開發概念,核心價值是讓 JavaScript 的模組化開發變得簡單自然。

SeaJS與RequireJS最大的差別:

SeaJS對模組的態度是懶執行, 而RequireJS對模組的態度是預執行

不明白?來看看這篇圖文並茂的文章吧:http://www.php.cn/

RequireJS API:http://www.php.cn/

RequireJS的用法:http:/ /www.php.cn/

為什麼要用requireJS

試想一下,如果一個網頁有很多的js文件,那麼瀏覽器在下載該頁面的時候會先載入js文件,從而停止了網頁的渲染,如果檔案越多,瀏覽器可能會失去回應。其次,要確保js檔案的依賴性,依賴性最大的模組(檔案)要放在最後加載,當依賴關係很複雜的時候,程式碼的編寫和維護都會變得困難。

RequireJS就是為了解決這兩個問題而誕生的:

(1)实现js文件的异步加载,避免网页失去响应;
(2)管理模块之间的依赖性,便于代码的编写和维护。
登入後複製

RequireJS檔案下載:http://www.php.cn/

AMD和CMD

CMD(Common Module Definition) 通用模組定義。此規範明確了模組的基本書寫格式和基本互動規則。該規範是在國內發展出來的。 AMD是依賴關係前置,CMD是按需載入。

在 CMD 規格中,一個模組就是一個檔案。程式碼的書寫格式如下:

define(factory);
登入後複製

factory 為函數時,表示是模組的建構方法。執行此構造方法,可以得到模組向外提供的介面。 factory 方法在執行時,預設會傳入三個參數:require、exports 和module:

define(function(require, exports, module) {

  // 模块代码

});
登入後複製

require是可以把其他模組導入進來的一個參數,而export是可以把模組內的一些屬性和方法導出的。

CMD規範位址:http://www.php.cn/

AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
登入後複製

對於依賴的模組,AMD 是提前執行,CMD 是延遲執行。

AMD:提前执行(异步加载:依赖先执行)+延迟执行
CMD:延迟执行(运行到需加载,根据顺序执行)
登入後複製

CMD 推崇依賴就近,AMD 推崇依賴前置。看如下程式碼:

// CMD
define(function(require, exports, module) {
var a = require(&#39;./a&#39;)
a.doSomething()
// 此处略去 100 行
var b = require(&#39;./b&#39;) // 依赖可以就近书写
b.doSomething()
// ... 
})

// AMD 默认推荐的是
define([&#39;./a&#39;, &#39;./b&#39;], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
...
})
登入後複製

另外一个区别是:

AMD:API根据使用范围有区别,但使用同一个api接口
CMD:每个API的职责单一
登入後複製

AMD的优点是:异步并行加载,在AMD的规范下,同时异步加载是不会产生错误的。
CMD的机制则不同,这种加载方式会产生错误,如果能规范化模块内容形式,也可以

jquery1.7以上版本会自动模块化,支持AMD模式:主要是使用define函数,sea.js虽然是CommonJS规范,但却使用了define来定义模块
所以jQuery已经自动模块化了

seajs.config({

&#39;base&#39;:&#39;/&#39;,

&#39;alias&#39;:{

    &#39;jquery&#39;:&#39;jquery.js&#39;//定义jQuery文件

}
});
登入後複製

define函数和AMD的define类似:

define(function(require, exports, module{

     //先要载入jQuery的模块

     var $ = require(&#39;jquery&#39;);

     //然后将jQuery对象传给插件模块

     require(&#39;./cookie&#39;)($);

     //开始使用 $.cookie方法

});
登入後複製

sea.js如何使用?

  • 引入sea.js的库

  • 如何变成模块?

    • define

  • 3.如何调用模块?

         -exports
         -sea.js.use
    登入後複製
  • 4.如何依赖模块?

         -require
    
    <script type="text/javascript">
           define(function (require,exports,module) {
               //exports : 对外的接口
               //requires : 依赖的接口
               require(&#39;./test.js&#39;);//如果地址是一个模块的话,那么require的返回值就是模块中的exports
           })
    登入後複製

sea.js 开发实例

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>鼠标拖拽的模块化开发实践</title>
<style type="text/css">
#p1{ width:200px; height:200px; background:black; position:absolute; display:none;}
#p2{ width:30px; height:30px; background:yellow; position:absolute; bottom:0; right:0;}
#p3{ width:100px; height:100px; background:blue; position:absolute; right:0; top:0;}
</style>
<script type="text/javascript" src="./sea.js"></script>
<script type="text/javascript">
    
//A同事 :
seajs.use(&#39;./main.js&#39;);
    
</script>
</head>

<body>
<input type="button" value="确定" id="input1" />
<p id="p1">
    <p id="p2"></p>
</p>
<p id="p3"></p>
</body>
</html>
登入後複製

A同事

//A同事写的main.js:

define(function (require,exports,module) {
    var oInput = document.getElementById(&#39;input1&#39;);
    var op1 = document.getElementById(&#39;p1&#39;);
    var op2 = document.getElementById(&#39;p2&#39;);
    var op3 = document.getElementById(&#39;p3&#39;);

    require(&#39;./drag.js&#39;).drag(op3);
    oInput.onclick = function () {
        op1.style.display = &#39;block&#39;;
        require(&#39;./scale.js&#39;).scale(op1,op2);

        require.async(&#39;./scale.js&#39;, function (ex) {
            ex.scale(op1,op2);
        })
    }
});
登入後複製

B同事

//B同事写的drag.js:

define(function(require,exports,module){
    
    function drag(obj){
        var disX = 0;
        var disY = 0;
        obj.onmousedown = function(ev){
            var ev = ev || window.event;
            disX = ev.clientX - obj.offsetLeft;
            disY = ev.clientY - obj.offsetTop;
            
            document.onmousemove = function(ev){
                var ev = ev || window.event;


                 var L = require(&#39;./range.js&#39;).range(ev.clientX - disX , document.documentElement.clientWidth - obj.offsetWidth , 0 );
                 var T = require(&#39;./range.js&#39;).range(ev.clientY - disY , document.documentElement.clientHeight - obj.offsetHeight , 0 );

                
                obj.style.left = L + &#39;px&#39;;
                obj.style.top = T + &#39;px&#39;;
            };
            document.onmouseup = function(){
                document.onmousemove = null;
                document.onmouseup = null;
            };
            return false;
        };
    }
    
    exports.drag = drag;//对外提供接口
    
});
登入後複製

C同事

//C同事写的scale.js:

define(function(require,exports,module){
    
    
    function scale(obj1,obj2){
        var disX = 0;
        var disY = 0;
        var disW = 0;
        var disH = 0;
        
        obj2.onmousedown = function(ev){
            var ev = ev || window.event;
            disX = ev.clientX;
            disY = ev.clientY;
            disW = obj1.offsetWidth;
            disH = obj1.offsetHeight;
            
            document.onmousemove = function(ev){
                var ev = ev || window.event;
                
                var W = require(&#39;./range.js&#39;).range(ev.clientX - disX + disW , 500 , 100);
                var H = require(&#39;./range.js&#39;).range(ev.clientY - disY + disH , 500 , 100);
                
                obj1.style.width = W + &#39;px&#39;;
                obj1.style.height = H + &#39;px&#39;;
            };
            document.onmouseup = function(){
                document.onmousemove = null;
                document.onmouseup = null;
            };
            return false;
        };
        
    }
    
    exports.scale = scale;
    
});
登入後複製

D同事

// D同事的range.js--限定拖拽范围

    define(function(require,exports,module){
        
        function range(iNum,iMax,iMin){
            
            if( iNum > iMax ){
                return iMax;
            }
            else if( iNum < iMin ){
                return iMin;
            }
            else{
                return iNum;
            }
            
        }
        
        exports.range = range;
        
    });
登入後複製

requirejs开发实例

require.config是用来定义别名的,在paths属性下配置别名。然后通过requirejs(参数一,参数二);参数一是数组,传入我们需要引用的模块名,第二个参数是个回调函数,回调函数传入一个变量,代替刚才所引入的模块。

main.js文件

//别名配置
requirejs.config({
    paths: {
        jquery: &#39;jquery.min&#39; //可以省略.js
    }
});
//引入模块,用变量$表示jquery模块
requirejs([&#39;jquery&#39;], function ($) {
    $(&#39;body&#39;).css(&#39;background-color&#39;,&#39;red&#39;);
});
登入後複製

引入模块也可以只写require()。requirejs通过define()定义模块,定义的参数上同。在此模块内的方法和变量外部是无法访问的,只有通过return返回才行.

define 模块

define([&#39;jquery&#39;], function ($) {//引入jQuery模块
    return {
        add: function(x,y){
            return x + y;
        }
    };
});
登入後複製

将该模块命名为math.js保存。

main.js引入模块方法

require([&#39;jquery&#39;,&#39;math&#39;], function ($,math) {
    console.log(math.add(10,100));//110
});
登入後複製

没有依赖

如果定义的模块不依赖其他模块,则可以:

define(function () {

    return {
        name: "trigkit4",
        age: "21"
    }
});
登入後複製

AMD推荐的风格通过返回一个对象做为模块对象,CommonJS的风格通过对module.exports或exports的属性赋值来达到暴露模块对象的目的。

以上就是详解JavaScript模块化开发的内容,更多相关内容请关注PHP中文网(www.php.cn)!


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

四款值得推薦的AI輔助程式工具 四款值得推薦的AI輔助程式工具 Apr 22, 2024 pm 05:34 PM

這個AI輔助程式工具在這個AI快速發展的階段,挖掘出了一大批好用的AI輔助程式工具。 AI輔助程式設計工具能夠提升開發效率、提升程式碼品質、降低bug率,是現代軟體開發過程中的重要助手。今天大姚給大家分享4款AI輔助程式工具(而且都支援C#語言),希望對大家有幫助。 https://github.com/YSGStudyHards/DotNetGuide1.GitHubCopilotGitHubCopilot是一款AI編碼助手,可幫助你更快、更省力地編寫程式碼,從而將更多精力集中在問題解決和協作上。 Git

AI程式設計師哪家強?探索Devin、通靈靈碼和SWE-agent的潛力 AI程式設計師哪家強?探索Devin、通靈靈碼和SWE-agent的潛力 Apr 07, 2024 am 09:10 AM

2022年3月3日,距離世界首個AI程式設計師Devin誕生不足一個月,普林斯頓大學的NLP團隊開發了一個開源AI程式設計師SWE-agent。它利用GPT-4模型在GitHub儲存庫中自動解決問題。 SWE-agent在SWE-bench測試集上的表現與Devin相似,平均耗時93秒,解決了12.29%的問題。 SWE-agent透過與專用終端交互,可以開啟、搜尋文件內容,使用自動語法檢查、編輯特定行,以及編寫和執行測試。 (註:以上內容為原始內容微調,但保留了原文中的關鍵訊息,未超過指定字數限制。)SWE-A

學習如何利用Go語言開發行動應用程式 學習如何利用Go語言開發行動應用程式 Mar 28, 2024 pm 10:00 PM

Go語言開發行動應用程式教學隨著行動應用程式市場的不斷蓬勃發展,越來越多的開發者開始探索如何利用Go語言開發行動應用程式。作為一種簡潔高效的程式語言,Go語言在行動應用開發中也展現了強大的潛力。本文將詳細介紹如何利用Go語言開發行動應用程序,並附上具體的程式碼範例,幫助讀者快速入門並開始開發自己的行動應用程式。一、準備工作在開始之前,我們需要準備好開發環境和工具。首

五大熱門Go語言庫總表:開發必備利器 五大熱門Go語言庫總表:開發必備利器 Feb 22, 2024 pm 02:33 PM

五大熱門Go語言庫總結:開發必備利器,需要具體程式碼範例Go語言自從誕生以來,受到了廣泛的關注和應用。作為一門新興的高效、簡潔的程式語言,Go的快速發展離不開豐富的開源程式庫的支援。本文將介紹五大熱門的Go語言庫,這些庫在Go開發中扮演了至關重要的角色,為開發者提供了強大的功能和便利的開發體驗。同時,為了更好地理解這些庫的用途和功能,我們會結合具體的程式碼範例進行講

Android開發最適合的Linux發行版是哪一個? Android開發最適合的Linux發行版是哪一個? Mar 14, 2024 pm 12:30 PM

Android開發是一項繁忙而又令人興奮的工作,而選擇適合的Linux發行版來進行開發則顯得尤為重要。在眾多的Linux發行版中,究竟哪一個最適合Android開發呢?本文將從幾個方面來探討這個問題,並給出具體的程式碼範例。首先,我們來看看目前流行的幾個Linux發行版:Ubuntu、Fedora、Debian、CentOS等,它們都有各自的優點和特點。

Go語言前端技術探秘:前端開發新視野 Go語言前端技術探秘:前端開發新視野 Mar 28, 2024 pm 01:06 PM

Go語言作為一種快速、高效的程式語言,在後端開發領域廣受歡迎。然而,很少有人將Go語言與前端開發聯繫起來。事實上,使用Go語言進行前端開發不僅可以提高效率,還能為開發者帶來全新的視野。本文將探討使用Go語言進行前端開發的可能性,並提供具體的程式碼範例,幫助讀者更了解這一領域。在傳統的前端開發中,通常會使用JavaScript、HTML和CSS來建立使用者介面

了解VSCode:這款工具到底是用來做什麼的? 了解VSCode:這款工具到底是用來做什麼的? Mar 25, 2024 pm 03:06 PM

《了解VSCode:這款工具到底是用來做什麼的? 》身為程式設計師,無論是初學者或資深開發者,都離不開程式碼編輯工具的使用。在眾多編輯工具中,VisualStudioCode(簡稱VSCode)作為一款開源、輕量級、強大的程式碼編輯器備受開發者歡迎。那麼,VSCode到底是用來做什麼的呢?本文將深入探討VSCode的功能和用途,並提供具體的程式碼範例,以幫助讀者

PHP在Web開發中是屬於前端還是後端? PHP在Web開發中是屬於前端還是後端? Mar 24, 2024 pm 02:18 PM

PHP在Web開發中是屬於後端。 PHP是一種伺服器端腳本語言,主要用於處理伺服器端的邏輯,產生動態網頁內容。與前端技術相比,PHP更多地用於與資料庫互動、處理使用者請求以及生成頁面內容等後端操作。接下來透過具體的程式碼範例來說明PHP在後端開發中的應用。首先,我們來看一個簡單的PHP程式碼範例,用於連接資料庫並查詢資料:

See all articles