javascript
【飞秋】JS 实现完美include
js為什么需要include?讓我們想想這樣1個場景,a.js 需要用到1個公用的common.js,當然你可以在用到a.js的頁面使用<script src="common.js">,但假設有5個頁面用到了a.js,你是不是要寫5遍<script。而且要是以后a.js 又需要引用common2.js,你是不是又的修改5個頁面了?
?
已有js include的一些問題
? 在寫這個之前在網上搜索了些資料,發現以前寫的include都存在2個問題,這也是include需要解決的比較重要的2個問題。
? 1、相對路徑的問題:? 在a.js中使用include("../js/common.js");? include 函數中肯定是使用相對路徑,是相對a.js的路徑。而a.js在html中使用<script>嵌入有可能是相對路徑,有可能是絕對路徑。? include函數如何才能真正確定common.js的絕對路徑,或者是相對html的相對路徑。網上一些為了解決這個問題,還需要加一些js變量,不方便。?
? 2、引用的問題。? 網上include函數的實現幾乎都是使用下面2種方式插入common.js????
document.write("<script src='" + .. + "></script>")?
或者???
var s = document.createElement("script");???
s.src = ...;???
head.insertAfter(s,...);???
document.write 輸出的腳本會在a.js后面加載,而createElement("script")創建的腳本是非阻塞加載。? 所以如果在common.js加載完畢之前,a.js中調用了common.js的函數就會報錯。
?
實現
?? 解決上面2個問題,就可以實現js include。?
? 第1個問題,我的方法是先獲取到a.js在html中的絕對路徑(如果是相對路徑,就轉為絕對路徑),然后再把common.js的路徑轉為絕對路徑。?
? 第2個問題,采用同步的ajax來請求common.js,這樣就不會出現引用問題。
?
實現代碼如下:
?
view sourceprint?01 // 根據相對路徑獲取絕對路徑?
02 function getPath(relativePath,absolutePath){?
03???? var reg = new RegExp("//.//./","g");?
04???? var uplayCount = 0;???? // 相對路徑中返回上層的次數。?
05???? var m = relativePath.match(reg);?
06???? if(m) uplayCount = m.length;?
07???????
08???? var lastIndex = absolutePath.length-1;??
09???? for(var i=0;i<=uplayCount;i++){?
10???????? lastIndex = absolutePath.lastIndexOf("/",lastIndex);?
11???? }?
12???? return absolutePath.substr(0,lastIndex+1) + relativePath.replace(reg,"");?
13 }????????
14???
15 function include(jssrc){?
16???? // 先獲取當前a.js的src。a.js中調用include,直接獲取最后1個script標簽就是a.js的引用。?
17???? var scripts = document.getElementsByTagName("script");?
18???? var lastScript = scripts[scripts.length-1];?
19???? var src = lastScript.src;?
20???? if(src.indexOf("http://")!=0 && src.indexOf("/") !=0){???????
21???????? // a.js使用相對路徑,先替換成絕對路徑?
22???????? var url = location.href;?
23???????? var index = url.indexOf("?");?
24???????? if(index != -1){?
25???????????? url = url.substring(0, index-1);?
26???????? }?
27???????????
28???????? src = getPath(src,url);?
29???? }?
30???? var jssrcs = jssrc.split("|");? // 可以include多個js,用|隔開?
31???? for(var i=0;i<jssrcs.length;i++){?
32???????? // 使用juqery的同步ajax加載js.?
33???????? // 使用document.write 動態添加的js會在當前js的后面,可能會有js引用問題?
34???????? // 動態創建script腳本,是非阻塞下載,也會出現引用問題?
35???????? $.ajax({type:'GET',url:getPath(jssrc,src),async:false,dataType:'script'});?
36???? }?
37 }
?
在a.js中直接使用 include("../js/common.js");
?
多請求的問題
使用上面的include看上去挺爽的,不過卻帶來另外1個嚴重的問題,就是多發送了1個ajax的請求。
我們常常為了WEB性能,而合并js,減少請求。但使用include后卻偏偏多了請求。如果這個問題不解決,相信很多人都不會在正式產品中使用include的了,除非是局域網產品。
?
如何解決這個多請求的問題,我也思考很久,最后覺的單單使用客戶端js是沒辦法解決了。所以就想到了使用服務端代碼來解決
還記的我之前有文章介紹 "js、css的合并、壓縮、緩存管理"的時候,就通過服務器端代碼在程序啟動時候去合并js。
?
所以我把include多請求的解決方案也加到里面去。就是在程序啟動的時候去查找所有的js,發現有使用include的就把include中common.js的源代碼替換該include函數。這樣a.js中在運行的時候就沒有include函數,而是真真包含了common.js的內容的js文件
?
后語
丫的。說到最后,怎么又把所有的include都替換掉了,哪之前說的那么多不白說了。
?
個人覺得,每個產品都應該要區分開發環境和產品環境(一般通過配置文件進行區分),在開發環境應該以開發效率為首要,而產品環境則以性能為首。所以這里的inlcude就應該要區分對待,在開發環境中使用js include來提高開發和維護效率,而在產品環境中則自動把所有include替換成真真的js文件的內容。
關注技術文章飛秋:http://www.freeeim.com/,24小時專業轉載。
?
總結
以上是生活随笔為你收集整理的【飞秋】JS 实现完美include的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uint8、double、mat2uin
- 下一篇: 深度理解高斯滤波器