easyloader.js原始碼分析

來源:互聯網
上載者:User

標籤:

http://www.cnblogs.com/jasonoiu/p/easyloader_source_code_analysis.html

Jquery easyui是一個javascript UI 組件庫,使用它可以快速開發企業級的業務系統。如果你正準備開發系統後台,可以選擇jquery easyui,也可以選擇Ext JS。我個人的看法是,如果Team Dev就兩三個人,開發工期很短,就一兩個月。那麼選擇jquery easyui就對了,jquery easyui原始碼量不多,便於閱讀和自行修改。而Ext JSy原始碼太多,短時間很難看完,學習曲線也比較陡峭。如果人手充足,時間也富裕,可以考慮使用Ext JS來開發,畢竟Ext JS更強大,控制項更多。

Jquery easyui是基於Jquery外掛程式機制擴充的,所以如果你很熟悉Jquery,那麼使用它開發會很簡單。

Jquery easyui的原始碼svn地址:http://jquery-easyui.googlecode.com/svn

easyloader模組是用來載入jquery easyui的js和css檔案的,而且它可以分析模組的依賴關係,先載入依賴項。模組載入好了會調用parse模組來解析頁面。把class是easyui開頭的標籤都轉化成easyui的控制項。

 

先看Demo1例子,再分析原始碼。

<!DOCTYPE HTML><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Demo1</title><script type="text/javascript" src="jquery-easyui-1.2.3/jquery-1.4.4.min.js"></script><script type="text/javascript" src="jquery-easyui-1.2.3/easyloader.js"></script></head><body>    <div class="easyui-panel" title="Demo1" fit="true" collapsible="true" minimizable="true" maximizable="true" closable="true" style="width: 100%; height: 200px;" >        easyloader會自動解析這個div,因為class屬性中帶有easyui開頭的類!    </div></body></html>

作者開發此模組,說明應該盡量使用easyuiloader來載入。因為他定製性更強,可以自訂佈景主題和國際化等。而壓縮過的檔案的優勢在於一次性把所有模組都載入進來,速度上更快。

  1 /**  2  * easyloader - jQuery EasyUI  3  *   4  * Licensed under the GPL:  5  *   http://www.gnu.org/licenses/gpl.txt  6  *  7  * Copyright 2010 stworthy [ [email protected] ]   8  *   9  */ 10 (function(){ 11     // 模組檔案定義 12     var modules = { 13         draggable:{ 14             js:‘jquery.draggable.js‘ 15         }, 16         droppable:{ 17             js:‘jquery.droppable.js‘ 18         }, 19         resizable:{ 20             js:‘jquery.resizable.js‘ 21         }, 22         linkbutton:{ 23             js:‘jquery.linkbutton.js‘, 24             css:‘linkbutton.css‘ 25         }, 26         pagination:{ 27             js:‘jquery.pagination.js‘, 28             css:‘pagination.css‘, 29             dependencies:[‘linkbutton‘] 30         }, 31         datagrid:{ 32             js:‘jquery.datagrid.js‘, 33             css:‘datagrid.css‘, 34             dependencies:[‘panel‘,‘resizable‘,‘linkbutton‘,‘pagination‘] 35         }, 36         treegrid:{ 37             js:‘jquery.treegrid.js‘, 38             css:‘tree.css‘, 39             dependencies:[‘datagrid‘] 40         }, 41         panel: { 42             js:‘jquery.panel.js‘, 43             css:‘panel.css‘ 44         }, 45         window:{ 46             js:‘jquery.window.js‘, 47             css:‘window.css‘, 48             dependencies:[‘resizable‘,‘draggable‘,‘panel‘] 49         }, 50         dialog:{ 51             js:‘jquery.dialog.js‘, 52             css:‘dialog.css‘, 53             dependencies:[‘linkbutton‘,‘window‘] 54         }, 55         messager:{ 56             js:‘jquery.messager.js‘, 57             css:‘messager.css‘, 58             dependencies:[‘linkbutton‘,‘window‘] 59         }, 60         layout:{ 61             js:‘jquery.layout.js‘, 62             css:‘layout.css‘, 63             dependencies:[‘resizable‘,‘panel‘] 64         }, 65         form:{ 66             js:‘jquery.form.js‘ 67         }, 68         menu:{ 69             js:‘jquery.menu.js‘, 70             css:‘menu.css‘ 71         }, 72         tabs:{ 73             js:‘jquery.tabs.js‘, 74             css:‘tabs.css‘, 75             dependencies:[‘panel‘,‘linkbutton‘] 76         }, 77         splitbutton:{ 78             js:‘jquery.splitbutton.js‘, 79             css:‘splitbutton.css‘, 80             dependencies:[‘linkbutton‘,‘menu‘] 81         }, 82         menubutton:{ 83             js:‘jquery.menubutton.js‘, 84             css:‘menubutton.css‘, 85             dependencies:[‘linkbutton‘,‘menu‘] 86         }, 87         accordion:{ 88             js:‘jquery.accordion.js‘, 89             css:‘accordion.css‘, 90             dependencies:[‘panel‘] 91         }, 92         calendar:{ 93             js:‘jquery.calendar.js‘, 94             css:‘calendar.css‘ 95         }, 96         combo:{ 97             js:‘jquery.combo.js‘, 98             css:‘combo.css‘, 99             dependencies:[‘panel‘,‘validatebox‘]100         },101         combobox:{102             js:‘jquery.combobox.js‘,103             css:‘combobox.css‘,104             dependencies:[‘combo‘]105         },106         combotree:{107             js:‘jquery.combotree.js‘,108             dependencies:[‘combo‘,‘tree‘]109         },110         combogrid:{111             js:‘jquery.combogrid.js‘,112             dependencies:[‘combo‘,‘datagrid‘]113         },114         validatebox:{115             js:‘jquery.validatebox.js‘,116             css:‘validatebox.css‘117         },118         numberbox:{119             js:‘jquery.numberbox.js‘,120             dependencies:[‘validatebox‘]121         },122         spinner:{123             js:‘jquery.spinner.js‘,124             css:‘spinner.css‘,125             dependencies:[‘validatebox‘]126         },127         numberspinner:{128             js:‘jquery.numberspinner.js‘,129             dependencies:[‘spinner‘,‘numberbox‘]130         },131         timespinner:{132             js:‘jquery.timespinner.js‘,133             dependencies:[‘spinner‘]134         },135         tree:{136             js:‘jquery.tree.js‘,137             css:‘tree.css‘,138             dependencies:[‘draggable‘,‘droppable‘]139         },140         datebox:{141             js:‘jquery.datebox.js‘,142             css:‘datebox.css‘,143             dependencies:[‘calendar‘,‘validatebox‘]144         },145         parser:{146             js:‘jquery.parser.js‘147         }148     };149     150     // 國際化資源檔151     var locales = {152         ‘af‘:‘easyui-lang-af.js‘,153         ‘bg‘:‘easyui-lang-bg.js‘,154         ‘ca‘:‘easyui-lang-ca.js‘,155         ‘cs‘:‘easyui-lang-cs.js‘,156         ‘da‘:‘easyui-lang-da.js‘,157         ‘de‘:‘easyui-lang-de.js‘,158         ‘en‘:‘easyui-lang-en.js‘,159         ‘fr‘:‘easyui-lang-fr.js‘,160         ‘nl‘:‘easyui-lang-nl.js‘,161         ‘zh_CN‘:‘easyui-lang-zh_CN.js‘,162         ‘zh_TW‘:‘easyui-lang-zh_TW.js‘163     };164     165     // 載入隊列166     var queues = {};167     168     /**169      * 載入js檔案函數,過程就是動態建立一個script標籤,然後添加到head標籤中去。170      * 有一個問題是監聽了script標籤的兩個事件函數,一個是onload,另一個是onreadystatechange,這個數要是針對IE和非IE瀏覽器準備的171      * 萬惡的IE瀏覽器!!!172      */173     function loadJs(url, callback){174         var done = false;175         var script = document.createElement(‘script‘);176         script.type = ‘text/javascript‘;177         script.language = ‘javascript‘;178         script.src = url;179         script.onload = script.onreadystatechange = function(){180             if (!done && (!script.readyState || script.readyState == ‘loaded‘ || script.readyState == ‘complete‘)){181                 done = true;182                 script.onload = script.onreadystatechange = null;183                 if (callback){184                     callback.call(script);185                 }186             }187         }188         document.getElementsByTagName("head")[0].appendChild(script);189     }190     191     /**192      * 執行js檔案。就是把js檔案載入進來,再remove掉193      * @param url js的url194      * @callback 回呼函數,執行完js時會調用這個函數195      */196     function runJs(url, callback){197         loadJs(url, function(){198             document.getElementsByTagName("head")[0].removeChild(this);199             if (callback){200                 callback();201             }202         });203     }204     205     /**206      * 載入css檔案。和載入js檔案一樣,動態建立一個link標籤,然後追加到head標籤中去207      * @param url css的url208      * @param callback 回呼函數,載入完成後調用此函數209      */210     function loadCss(url, callback){211         var link = document.createElement(‘link‘);212         link.rel = ‘stylesheet‘;213         link.type = ‘text/css‘;214         link.media = ‘screen‘;215         link.href = url;216         document.getElementsByTagName(‘head‘)[0].appendChild(link);217         if (callback){218             callback.call(link);219         }220     }221     222     /**223      * 載入單獨的一個模組224      */225     function loadSingle(name, callback){226         227         // 載入隊列存入該模組名,並表示狀態為loading。228         queues[name] = ‘loading‘;229         230         // 根據模組名,取出該模組定義231         var module = modules[name];232         233         // js載入狀態234         var jsStatus = ‘loading‘;235         236         // css載入狀態,從這裡你就可以看出easyloader.css就是一個開關變數,控制是否載入模組相應的css檔案237         var cssStatus = (easyloader.css && module[‘css‘]) ? ‘loading‘ : ‘loaded‘;238         239         // 是css檔案,就使用loadCss來載入之240         if (easyloader.css && module[‘css‘]){241             if (/^http/i.test(module[‘css‘])){242                 var url = module[‘css‘];243             } else {244                 var url = easyloader.base + ‘themes/‘ + easyloader.theme + ‘/‘ + module[‘css‘];245             }246             loadCss(url, function(){247                 cssStatus = ‘loaded‘;248                 if (jsStatus == ‘loaded‘ && cssStatus == ‘loaded‘){249                     finish();250                 }251             });252         }253         254         // 是js檔案,就是用LoadJs來載入之255         if (/^http/i.test(module[‘js‘])){256             var url = module[‘js‘];257         } else {258             var url = easyloader.base + ‘plugins/‘ + module[‘js‘];259         }260         loadJs(url, function(){261             jsStatus = ‘loaded‘;262             if (jsStatus == ‘loaded‘ && cssStatus == ‘loaded‘){263                 finish();264             }265         });266         267         // 最終調用finish函數,來結束載入。並觸發onProgress函數,每載入成功一個模組,就調用一次onProgress268         function finish(){269             queues[name] = ‘loaded‘;270             easyloader.onProgress(name);271             if (callback){272                 callback();273             }274         }275     }276     277     /**278      * easyui模組載入函數279      * @param name 模組名,可以是string,也可以是數組280      * @param callback 回呼函數,當載入結束後會調用此函數281      */282     function loadModule(name, callback){283         284         // 模組名,根據依賴關係,從前到後,依次排開285         var mm = [];286         287         // 載入標識,當其值為true時,表示需要載入的模組已經載入好了288         var doLoad = false;289         290         // 模組名支援兩中,一種是string,一種是數組。這樣就可以一次載入多個模組了291         if (typeof name == ‘string‘){292             // 是string的時候,調用add方法把模組名push到mm數組中去293             add(name);294         } else {295             for(var i=0; i<name.length; i++){296                 // 是數組的時候,迴圈調用add方法把模組名統統push到mm數組中去297                 add(name[i]);298             }299         }300         301         /**302          * loadModule函數中內嵌的一個函數,用來載入模組名到變數mm數組中去303          * @param name 模組名,只能是string304          */305         function add(name){306             // 保護措施,如果該模組名不存在,我們就不要載入了307             if (!modules[name]) return;308             309             // 否則,就是該模組存在。然後,我們在看看其有沒有相依模組310             var d = modules[name][‘dependencies‘];311             if (d){312                 // 如果有相依模組,我們要先把相依模組的名字push到mm中去313                 // 這裡用了遞迴調用314                 for(var i=0; i<d.length; i++){315                     add(d[i]);316                 }317             }318             319             // 把模組名放到mm中320             mm.push(name);321         }322         323         /**324          * 當一個模組及其相依模組載入完成時,執行回呼函數,並且觸發onLoad函數325          */326         function finish(){327             if (callback){328                 callback();329             }330             easyloader.onLoad(name);331         }332         333         // 載入用時334         var time = 0;335         336         /**337          * 載入所需要的模組,需要的模組,我們已經統計好了,並按依賴關係,先後push到mm中去了338          */339         function loadMm(){340             // 判斷mm是不是空的341             if (mm.length){342                 343                 // 第一個模組344                 var m = mm[0];345                 346                 // 判斷載入隊列是否包含此模組347                 if (!queues[m]){348                     349                     // 載入隊列不包含此模組,開始載入該模組350                     // 把doLoad置成true,表示開始載入351                     doLoad = true;352                     353                     // 調用loadSingle方法來載入模組,載入成功後會把此模組從mm中shift掉,然後繼續調用loadMM方法,就形成了遞迴調用354                     loadSingle(m, function(){355                         mm.shift();356                         loadMm();357                     });358                 } else if (queues[m] == ‘loaded‘){359                     // 載入隊列已經載入過此模組了,不需要在載入了,直接從mm中shift掉即可360                     mm.shift();361                     loadMm();362                 } else {363                     // 表示正在載入該模組,累計所用時間如果沒有超過timeout364                     // 則過10毫秒再調用一次loadMm函數365                     if (time < easyloader.timeout){366                         time += 10;367                         setTimeout(arguments.callee, 10);368                     }369                 }370             } else {371                 // 走到這裡,表示該載入的模組都已經載入好了372                 if (easyloader.locale && doLoad == true && locales[easyloader.locale]){373                     // 如果設定了國際化,並且已經載入好了,而且該國際化資源還存在,那麼載入該資源js374                     var url = easyloader.base + ‘locale/‘ + locales[easyloader.locale];375                     376                     // 執行js完事後,調用finish方法377                     runJs(url, function(){378                         finish();379                     });380                 } else {381                     // 沒定義國際化檔案,那麼直接調用finish方法吧382                     finish();383                 }384             }385         }386         387         loadMm();388     }389     390     /**391      * easyloader定義為全域變數392      */393     easyloader = {394         395         // 各個模組檔案的定義,包括js、css和相依模組396         modules:modules,397         398         // 國際化資源檔399         locales:locales,400         401         // jquery-easyui的根目錄,在載入easyloader時,會自動根據你放置的位置而改變402         base:‘.‘,403         404         // 控制項的主題,一共就有兩個,在theme目錄中。還有一個gray主題,淺灰色的,很難看。405         theme:‘default‘,406         407         // 這是一個開關變數,控制easyloader載入模組時,要不要載入相應的css檔案,預設是需要載入的408         css:true,409         410         // 國際化語言,可以根據window.navigator.language或者window.navigator.userLanguage來擷取當前瀏覽器的語言。411         // 有兩個屬性,主要因為IE瀏覽器只認識userLanguage和sysLanguage,萬惡的IE瀏覽器啊!412         locale:null,413         414         // 載入一個模組的最長時間,超過這個時間,就開始載入下一個模組了。415         timeout:2000,416     417         // easyloader就公開了這麼一個方法,用來載入模組。418         // name是模組名,callback是載入成功後執行的函數419         load: function(name, callback){420             if (//.css$/i.test(name)){421                 // 如果模組名是以.css結尾422                 423                 if (/^http/i.test(name)){424                     // 如果模組名是以http開頭,那麼css是一個檔案的url425                     loadCss(name, callback);426                 } else {427                     // 否則,說明模組名相對於jquery easyui根目錄來說的428                     loadCss(easyloader.base + name, callback);429                 }430             } else if (//.js$/i.test(name)){431                 // 如果模組名是以.js結尾432                 433                 if (/^http/i.test(name)){434                     // 如果模組名是以http開頭,那麼js是一個檔案的url435                     loadJs(name, callback);436                 } else {437                     // 否則,說明模組名相對於jquery easyui根目錄來說的438                     loadJs(easyloader.base + name, callback);439                 }440             } else {441                 // 以上兩種都不是,說明是easyui自己的模組,直接使用loadModule來載入,就可以了442                 loadModule(name, callback);443             }444         },445         446         // 當一個模組載入完會觸發此函數447         onProgress: function(name){},448         449         // 當一個模組和其依賴都載入完會觸發此函數450         onLoad: function(name){}451     };452     /**453      * 這一小段代碼就是尋找jquery-easyui的根目錄,並賦值給easyloader的base屬性上。這樣easyloader再載入css檔案和js檔案就很方便定位了。454      */455     var scripts = document.getElementsByTagName(‘script‘);456     for(var i=0; i<scripts.length; i++){457         var src = scripts[i].src;458         if (!src) continue;459         var m = src.match(/easyloader/.js(/W|$)/i);460         if (m){461             easyloader.base = src.substring(0, m.index);462         }463     }464     /**465      * 這個就起一個別名的作用,比如頁面中可以想如下這麼下:466      * using(‘window‘);467      * 這樣window模組就載入進來了!468      */469     window.using = easyloader.load;470     /**471      * easyloader.js載入的第一模組是parse模組,parser模組調用parse方法,可以解析頁面上的easyui控制項472      */473     if (window.jQuery){474         jQuery(function(){475             easyloader.load(‘parser‘, function(){476                 jQuery.parser.parse();477             });478         });479     }480     481 })();

easyloader.js原始碼分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.