問題背景
前端采用的 iframe + html 做后台管理系統。現在js、jquery插件非常多,每次頁面都是引用就類似這樣:
<script src="../Scripts/jquery-1.7.1.js"></script> <script src="../Scripts/uploadify/jquery.uploadify.js"></script> <script src="../Scripts/uploadify/swfobject.js"></script> <link href="../Scripts/uploadify/uploadify.css" rel="stylesheet" />
有時候需要更新其中一個組件,為了避免客戶端瀏覽器手動刷新,一般的做法是增加版本號,比如 xxx.js?v=1111。
或者說,需要刪掉某個組件,引用某個組件。
在這2種情況下,都需要針對每個頁面,增加 script 引用。每次新建一個html,就要把之前的頁面的 script 引用都復制過來,有木有?
解決辦法
現在有Require.js , sea.js ,labjs 等等各種高大上的框架。
以上框架中,樓主僅試過用lab.js解決這種問題,它可以很好的控制腳本的異步加載,以及腳本的依賴,然后可以在腳本加載完畢后,做初始化的操作。當時僅僅是做了一個Demo,一直過了很長時間,也沒有使用,原因無它,如果希望能控制腳本的動態加載時,又希望像以前一樣直接在頁面上引用script,換句話來說,樓主要的不是重寫腳本引用方式,而是在原有基礎上稍作改善。
關鍵方法很簡單,使用了 document.writeIn('...') 來加載。這種加載方式,是同步加載,就是它了。
具體思路則是,定義一個數組存放腳本以及css路徑,建議使用絕對路徑,這樣不會因為頁面所在的位置而導致腳本加載不上。
然后做了一點點小改進,同步加載js,異步加載css。同時支持設置版本號,這樣可以輕松控制客戶端的自動更新。大致實現代碼如下:
在實際應用過程中,這個js腳本,是會經常發生變更,所以必須再通過 document.writeIn 加載這個腳本。首先可以以如下形式寫在頁面中
<script> document.writeIn('...'); </script>
這樣略微不方便啦。於是樓主又寫了一個腳本,僅僅只有如上一行代碼,就是用來控制加載前面定義通用的腳本組件。這個只有一行代碼的腳本,是萬年不變的,所有頁面直接引用即可,由它來控制后面的腳本變化。
測試
上面說,腳本加載的形式是同步的,為了證明這一點,樓主不得不寫一點簡單的例子。看看下面的html代碼:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> </head> <body> <input type="text" id="uid" value="111" /> </body> </html> <script src="Scripts/com/boot.js"></script> <script> alert($("#uid").val()); </script>
而boot.js就是引導腳本,就是之前提到的一行代碼:
/*引導加載所有的js文件*/document.writeln("<script src='/Scripts/com/bootallscript.js?v=" + Math.random() + "'><\/script>");
bootallscript.js就是最核心的了,復雜加載所有的js和css。
(function () { var base = '/Scripts/'; var loader = { base: '/Scripts/', ver: 1, content: [ //定義需要加載的腳本 'jquery-1.7.1.min.js' ], loadcss: function (cssUrl) { var link = document.createElement("link"); link.rel = "stylesheet"; link.type = "text/css"; link.href = cssUrl; document.getElementsByTagName("head")[0].appendChild(link); }, run: function () { for (var i in loader.content) { var c = loader.content[i]; if (c.length <= 2) continue; var p = loader.base + c + "?v=" + loader.ver;; var type = c.substr(c.length - 2, c.length); if (type === 'js') { //同步加載js文件 document.writeln("<script src='" + p + "' ><\/script>"); } else { //異步加載css文件 loader.loadcss(p); } } } }; //加載js腳本 loader.run(); })();
運行后會發現,頁面在加載完成后,使用jQuery獲取到了控件的值。這種方式和原來的直接腳本引用,差別不大吧。
說到這里,我們新建頁面后,只需要引用 boot.js就能加載上所有的組件,而頁面邏輯相關的js,也可以直接引用在boot.js下方,沒有改變原來的腳本引用習慣,又能極大的節省了代碼,完善對腳本的控制,這就是樓主想要的效果了。
寫在最后,當然mvc對類似的問題有了解決方案,這里不探討,因為討論的是 前端 iframe+html 無 C# 。