requirejs使用入門javascript
RequireJS的目標是鼓勵代碼的模塊化,它使用了不一樣於傳統<script>標籤的腳本加載步驟。能夠用它來加速、優化代碼,但其主要目的仍是爲了代碼的模塊化。它鼓勵在使用腳本時以module ID替代URL地址。html
RequireJS以一個相對於baseUrl的地址來加載全部的代碼。 頁面頂層<script>標籤含有一個特殊的屬性data-main,require.js使用它來啓動腳本加載過程,而baseUrl通常設置到與該屬性相一致的目錄。java
咱們在作項目的過程當中,每每都須要加載不少個js文件,以下所示:jquery
<script src="1.js"></script> <script src="2.js"></script> <script src="3.js"></script> <script src="4.js"></script> <script src="5.js"></script> <script src="6.js"></script>
這樣的寫法的缺點是Js會阻塞渲染頁面,而且文件越多, 那麼等待的時間也就越長,而且文件多的狀況下每每還存在文件間依賴的問題, 有時候比較複雜,那麼文件間的依賴就成了問題。git
因此require.js主要就是爲了解決下面的兩個問題:github
(1)實現js文件的異步加載,避免頁面失去響應。ajax
(2)管理項目之間的依賴性,便於代碼的維護和管理。api
使用require.js很是簡單,只須要在頁面中使用一個require.js便可,以下所示:瀏覽器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>require</title> <script src="./require.js" data-main="js/main" type="text/javascript"></script> </head> <body> <!-- your code is here --> </body> </html>
即咱們在html文件中只須要使用一個require.js文件的引入便可,而後data-main引入的是網頁程序的主模塊,這個文件會被require.js第一個加載,因爲require.js默認文件的後綴名爲.js,因此這裏咱們寫成main便可。
什麼是主模塊?
主模塊就是入口文件,它是require.js加載執行的第一個文件,這就是主模塊,而且其餘的全部js文件將在這裏被引入執行。
爲何要使用主模塊?
咱們知道require.js在index.html惟一的被引入,而沒有引入其餘js文件,這也是爲了方便管理。 那麼內部機制就要求須要這麼一個主模塊,而後就能夠很好的管理模塊之間的關係,試想若是沒有這麼一個主模塊,那麼require.js也會無從下手的。
main.js中怎麼寫呢? 若是咱們只須要這一個js就夠了,好比就執行alert("hello");那麼main.js文件中只有這麼一句:
alert("hello");
而後打開html文件時,就會alert("hello");了,可是咱們使用require.js不可能就使用這麼一個文件,不然就不用require了。
真正的狀況是: 主文件main.js依賴於其餘文件, 這時就要使用AMD規範來定義require()函數。以下所示:
// main.js require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){ // some code here });
即接受的第一個參數是一個數組,指定模塊名稱(不帶.js的文件), 而後第二個參數是一個函數,其中的參數暴露出了模塊中暴露的方法,而後咱們就能夠在回調函數中使用這些模塊了。
require()異步加載moduleA,moduleB和moduleC,瀏覽器不會失去響應;它指定的回調函數,只有前面的模塊都加載成功後,纔會運行,解決了依賴性的問題。
好比以前的index.html中的body部分是<div class="wrap"></div>,而後引入了require.js並指定了main.js爲入口文件,在main.js中定義以下:
require(['jquery'],function ($) { $('.wrap').html("hello, world!"); });
即咱們只引入了jquery,而且在回調函數中將$暴露出來並使用,那麼啓動index.html文件以後,咱們就能夠在頁面上看到渲染的hello, world了。 注意: 此時的目錄結構以下:
因此:咱們須要注意下面的幾點:
、
存在的問題: 若是說依賴文件(如jquery)何main.js文件再也不同一個目錄中該怎麼引用呢?
好比如今的目錄時這樣的:
那麼如今咱們就會發現,你在require函數的第一個參數中寫成'jquery'或者‘lib/jquery’或者‘../lib/jquery’或者‘./lib/jquery’都是沒法成功的。
這時咱們就須要使用require.config()方法對路徑進行配置了。以下所示:
require.config({ paths: { jquery: '/lib/jquery' } });
若是有多個文件,而且多個文件在一樣的目錄下,咱們能夠定義一個baseUrl, 以下:
require.config({ baseUrl: "js/lib", paths: { "jquery": "jquery.min", "underscore": "underscore.min", "backbone": "backbone.min" } });
若是某個模塊在另外一個主機上,咱們能夠直接定義其網址:
require.config({ paths: { "jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min" } });
在使用require時,咱們用的是AMD的規範進行加載的,因此在定義模塊時,也是須要使用AMD規範來定義模塊。
好比如今咱們在和main.js同一個目錄下定義一個alert模塊:
define(function () { var alertName = function (str) { alert("I am " + str); } var alertAge = function (num) { alert("I am " + num + " years old"); } return { alertName: alertName, alertAge: alertAge }; });
即便用define定義,其中接受一個回調函數做爲參數,在這個回調函數中定義模塊,最後返回一個對象,對象的屬性就是咱們能夠調用的方法。
而後咱們看看如何在main.js中使用:
require(['alert'], function (alert) { alert.alertName('JohnZhu'); alert.alertAge(21); });
即便用也很是簡單,就是引入alert模塊,而後調用其中的alertName和alertName方法便可。
問題:若是一個模塊在定義時須要依賴其餘模塊怎麼辦?
好比這個alert模塊須要依賴jquery,那麼咱們就能夠這麼定義:
define(['jquery'],function () { var alertName = function (str) { alert("I am " + str); $('.wrap').html("I am " + str); } var alertAge = function (num) { alert("I am " + num + " years old"); } return { alertName: alertName, alertAge: alertAge }; });
即咱們直接將define的第一個參數(一個數組)中使用jquery, 而後直接使用便可。
理論上,require.js加載的模塊,必須是按照AMD規範、用define()函數定義的模塊。可是實際上,雖然已經有一部分流行的函數庫(好比jQuery)符合AMD規範,更多的庫並不符合。那麼,require.js是否可以加載非規範的模塊呢?
答案是能夠的,可是須要在使用require以前,用require.config()方法定義一些他們的特徵。
require.config({ shim: { 'underscore':{ exports: '_' }, 'backbone': { deps: ['underscore', 'jquery'], exports: 'Backbone' } } });
以前咱們介紹過require.config中的paths,這裏又介紹了shim對象,它專門用來配置不兼容的模塊。具體來講,每一個模塊要定義:
(1)exports值(輸出的變量名),代表這個模塊外部調用時的名稱;
(2)deps數組,代表該模塊的依賴性。
好比,咱們能夠這樣定義一個jquery插件:
shim: { 'jquery.scroll': { deps: ['jquery'], exports: 'jQuery.fn.scroll' } }
即deps說明他是須要依賴jquery的, exports說明能夠經過juqery的scroll訪問到它。
requirejs還提供了一系列的插件供咱們使用。
domready插件,可讓回調函數在頁面DOM結構加載完成後再運行。
require(['domready!'], function (doc){ // called once the DOM is ready });
text和image插件,則是容許require.js加載文本和圖片文件。
define([ 'text!review.txt', 'image!cat.jpg' ], function(review,cat){ console.log(review); document.body.appendChild(cat); } );
最近看到有人相似於這樣使用require。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>require</title> <script src="./require.js" type="text/javascript"></script> </head> <body> <!-- your code is here --> <div class="wrap"> </div> <script> require(['js/dosomething']); </script> <script src="js/jquery.js"></script> </body> </html>
dosomething是這樣的:
alert('god');
參考文檔: