iT邦幫忙

12

實用 JavaScript 工具庫:RequireJS

平常寫些複雜的論述寫久了,這次來寫點小工具的介紹。:)

平常我們讀取 JavaScript ,大家都不陌生的一定是滿滿的 script tag ,
但是當我們要多使用到一個函式庫時或是突然發現有些 js 檔用不到時,
一一去刪除或新增這些 script tag 常常讓我們覺得很困擾。

有時候當我們覺得一個檔案越寫越大,想要把部份獨立功能放到另一個檔案時,
可能也會擔心會忘記更新 script tag 而造成問題而舉步不前。

RequireJS 就是發展來協助你讀取 JS 檔案成為你系統中的模組的一個工具。

@ 這麼神奇,那他是什麼? 要怎麼用?

RequireJS 本身當然也是一個 JS 檔,他的用法很簡單,
可以先到官方網站下載 requireJS 的 JS 檔。

http://requirejs.org/docs/download.html

假設你網頁原本執行 main.js 前,需要讀取 a.js,b.js,c.js,d.js ,
你的原始碼原本可能會是

<script src="scripts/a.js"></script>
<script src="scripts/b.js"></script>
<script src="scripts/c.js"></script>
<script src="scripts/d.js"></script>
<script src="scripts/main.js"></script>

那換成 requireJS 的版本的情況下,你會改寫成以下程式碼:

<script src="scripts/require.js" data-main="main" ></script>

頁面上只會留這樣一行!

原本 a.js , b.js ,c.js ,d.js 都消失了,
這指令除了會協助你載入 require.js 以外,還會自動幫你讀取 main.js。

當然,你也可以修改 data-main 像是 data-main="my" 來讀取 my.js 或其他任意 JS。

這裡因為我們需要在使用 main.js 時引用 a,b,c,d ,所以接著我們還需要對 main.js 做一些修改。

main.js

require(["a","b","c","d"],function(a,b,c,d){
  //原本的程式碼
});

透過這樣的方式可以由系統幫你載入 a.js,b.js,c.js,d.js 4 個 JS 檔,
這裡 a,b,c,d 只是個代名詞,如果我們舉個更真實的例子,相信大家會更有感覺。


像我們常見的 jQuery 、jQuery-ui等套件,只要將 JS 放在同一個 scripts 資料夾,就可以透過底下的程式碼進行操作

require(["jquery","jquery-ui"], function($,ui) {
  $(function(){
    $(document.body).append("jQuery:"+($!=null)+"<br />,jQuery UI loaded:"+
    ($.fn.draggable != null));
  });
});

這裡有一個測試案例可以參考:
http://files.tonyq.org/requirejs/v1/app.html

在調用 require 函式時,我們給入了一個字串陣列 ["jquery","jquery-ui"] ,這意味著他將在 main.js 所在的目錄內試著讀取 jquery.js 、jquery-ui.js 並且在讀取完成後,呼叫我們所給的 callback 函式。

這樣一來,我們就可以透過他協助我們讀取 dependency ,而不用人工一一設定 script tag,並且藉此可以避免許多問題。

像我們也常常碰到一個問題,我可能一開始只需要用到 a,b,c 三個套件,但後來我又用到 d,e,f 三個套件,在過去我們常常會需要再一開始就引入 a,b,c,d,e,f 六個套件以免發生相依性衝突,但現在我們只需要在我們需要的時候下一個簡單的 require() 函式並且告訴他我們需要的函式,由他替我們處理函式庫的載入問題。

因為同樣的套件在 require 之中只會被讀取一次,所以我們不用擔心會因為重複讀取造成問題,在複雜的動態頁面中特別好用。

像在下面這個例子裡面,我們示範了如何完全很直覺的在事件內動態載入 jQuery UI 並且直接在頁面 dom 上綁入 date-picker 事件。

require(["jquery"], function($,ui) {
	$(function(){
		var d = new Date();
		$("#input").val(d.getMonth()+"/"+d.getDate()+"/"+d.getFullYear());
		$("#date").show().one("click",function(){
			require(["jquery-ui"],function(){
				$("#input").show();
				$("#date").hide();
				$("#input").datepicker();
			});
		});
	});
	
});

示範網址
http://files.tonyq.org/requirejs/v2/app.html

當然就真實世界而言,這個例子不是非常的好,像是 jQuery-ui 函式庫太大所以會導致載入的時間有點久,而出現讀取時有點卡卡的狀況,但這裡要說明的是他在動態載入上相當的有彈性與簡便。

比起過去我們努力寫 Script 自己管理相依性,處理這些複雜的工作,
RequireJS 顯然已經成為我們用來讀取 JS、管理 JS 的主流工具。

當然 RequireJS 本身使用方法跟傳統 Script tag 有些不一樣,有很多東西我們無法在這篇文章一一介紹。像是因為 RequireJS 不會重複讀取 JS 檔案,如何定義 RequireJS 的模組來達到重複呼叫函式的效果。以及我們過去習慣合併多個 JS 檔案成為一個 JS 檔案,當我們使用 RequireJS 去讀取檔案時,RequireJS 也有很方便的工具可以協助我們妥善處理 dependency 與打包的工具。(r.js)

這些進階的應用與 RequireJS 的介紹,大家都可以在 RequireJS 網站上找到相關說明:http://requirejs.org/

你還在煩惱 Script tag 很難管理嗎? RequireJS 就是你的好朋友與最摩登的現代工具。:)


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
我是老皮
iT邦新手 4 級 ‧ 2013-05-14 16:44:25

好文,推一下 讚

0
muji767
iT邦新手 5 級 ‧ 2013-07-23 11:38:49

想請問大家要達到全部都用requirejs 管理,不同頁面須"特定模組/功能",該如何獨立加載?
例如:

&lt;pre class="c" name="code">
a.html
&lt;script data-main="scripts/main" src="require.js">&lt;/script>
&lt;script >a.js&lt;/script>
&lt;hr>
b.html
&lt;script data-main="scripts/main" src="require.js">&lt;/script>
&lt;script >b.js&lt;/script>

一直嘗試失敗,希望大家能給點方向。能夠完全使用requirejs 單檔管理加載嗎?並達到不同頁面不同特定模組

我要留言

立即登入留言