javascript的動(dòng)態(tài)加載、緩存、更新以及復(fù)用(一)
使用范圍:
OA、MIS、ERP等信息管理類的項(xiàng)目,暫時(shí)不考慮網(wǎng)站。
遇到的問(wèn)題:
完成一個(gè)項(xiàng)目,往往需要引用很多js文件,比如jQuery.js、easyUI等。還有自己寫的一些列js文件,那么這些文件如何方便的加載,如果文件有變化如何才能讓客戶端及時(shí)更新緩存?如果能夠提高點(diǎn)運(yùn)行效率,那就更好了。
目標(biāo):
1、 可以方便的引用js文件。
2、 盡量使用各種緩存,避免頻繁從服務(wù)器讀取文件。
3、 如果js文件有更新或者增加、減少幾個(gè)減少js文件,需要客戶端能夠自動(dòng)、立刻更新。
4、 Js文件的復(fù)用。
頁(yè)面結(jié)構(gòu):
一般OA、MIS這一類的項(xiàng)目,大多采用frameset或者iframe的方式來(lái)實(shí)現(xiàn),這樣就有了父頁(yè)和子頁(yè)的概念。我們可以利用這一點(diǎn)來(lái)做做文章。
網(wǎng)頁(yè)可以分為三塊:外殼、首頁(yè)、標(biāo)簽、數(shù)據(jù)列表、表單(添加、修改)。因?yàn)檫@里要說(shuō)的加載js的方法,需要利用這種頁(yè)面結(jié)構(gòu),也正是因?yàn)檫@個(gè)原因,所以暫時(shí)不支持網(wǎng)站。
看這個(gè)圖有點(diǎn)眼熟吧。恩,就是這種結(jié)構(gòu)。
正文
現(xiàn)在做web版的應(yīng)用,越來(lái)越依賴各種js了,第三方的jQuery、easyUI、my97等,還有自己寫的各種js。要實(shí)現(xiàn)的功能越來(lái)越多,需要使用的js也越來(lái)越多,js文件的修改也很頻繁。于是就出現(xiàn)了許多問(wèn)題,比如每個(gè)頁(yè)面都要寫一大堆<script src=””>。這個(gè)也太麻煩了吧,增加一個(gè)新的js文件,需要改多少頁(yè)面?js文件更新了如何讓客戶端也立即更新?如何讓客戶端更快的加載js。有的Js文件還有依賴關(guān)系,如何確保加載順序?本文內(nèi)容就是分享一下我的解決方案。
動(dòng)態(tài)加載
在頁(yè)面里使用<script>加載js,顯然很麻煩,那么怎么辦呢?想來(lái)想去還是用動(dòng)態(tài)加載的方法來(lái)解決。在網(wǎng)上也搜索了一番,有很多種方法,有自己手動(dòng)寫的,有整理成框架的(比如seejs)。有的時(shí)候還是感覺(jué)自己弄一個(gè)更加的應(yīng)手,所以打算自己寫一套。
如何動(dòng)態(tài)加載呢?使用jQuery提供的方法嗎?這個(gè)倒是可以,但是頁(yè)面必須引用jQuery和我寫的加載js文件的js。也就是說(shuō)一個(gè)頁(yè)面要寫兩個(gè)<script>,這個(gè)就麻煩了。能寫一個(gè),就一定不要寫兩個(gè),雖然只是多了一個(gè),但是多了這么一個(gè)就真的很麻煩。所以決定自己手寫一個(gè)動(dòng)態(tài)加載的小方法。
不會(huì)寫怎么辦呢?百度大嬸來(lái)幫忙吧。各種搜呀,終于找到了一個(gè)比較理想的方法,恩就用這個(gè)了。
/*實(shí)現(xiàn)動(dòng)態(tài)加載js的函數(shù),來(lái)自于互聯(lián)網(wǎng),做了一點(diǎn)修改,可以兼容IE10 */
var loadscript =
{
$$: function(id) { return document.getElementById(id); },
tag: function(element) { return document.getElementsByTagName(element); },
ce: function(element) { return document.createElement(element); },
js: function(url, callback) {
var s = loadscript.ce('script');
s.type = "text/javascript";
s.src = url;
if (document.documentMode == 10 || document.documentMode == 9) {
s.onerror = s.onload = loaded;
} else {
s.onreadystatechange = ready;
s.onerror = s.onload = loaded;
}
loadscript.tag('head')[0].appendChild(s);
function ready() { /*IE7.0/IE10.0*/
if (s.readyState == 'loaded' || s.readyState == 'complete') {
callback();
}
}
function loaded() { /*chrome/IE10.0*/
callback();
}
}
};
加載順序
和新代碼已經(jīng)搞定了,下面就是如何加載其他js文件了,由于文件比較多,還有一定的依賴關(guān)系,想來(lái)想去還是弄個(gè)js文件的字典吧,然后做一個(gè)加載順序,按照這個(gè)順序來(lái)加載。
為了更穩(wěn)定一點(diǎn),決定采用一個(gè)一個(gè)加載的方式,即加載完一個(gè)js,然后在加載另一個(gè)js。這樣就可以確保依賴關(guān)系。當(dāng)然缺點(diǎn)是加載速度會(huì)比較慢。一般網(wǎng)頁(yè)加載js是可以多個(gè)js文件一起下載的,這個(gè)速度就會(huì)比較快。
使用緩存
一般瀏覽器對(duì)于各種資源(比如網(wǎng)頁(yè)、圖片、js、css等)會(huì)有一個(gè)緩存,已經(jīng)有了就不會(huì)再向服務(wù)器去下載了??此坪芎?,但是有兩個(gè)問(wèn)題:
A、瀏覽器如何判斷緩存的js文件是不是最新的?
B、js文件更新了,如何強(qiáng)制瀏覽器更新?
瀏覽器是怎么判斷的呢?具體步驟我也不太清楚,只是知道有一個(gè)步驟是要到服務(wù)器問(wèn)問(wèn),我緩存的js文件是不是最新的,然后才能夠確定本地的緩存是否是最新的,如果是最新的就不折騰了,如果不是再去下載最新的。就是說(shuō)呢,即使客戶端已經(jīng)有了js文件的緩存,但是瀏覽器要確認(rèn)一下是否最新,還是會(huì)跑到服務(wù)器去問(wèn)問(wèn)。這個(gè),折騰呀。當(dāng)然一般情況下,這個(gè)過(guò)程會(huì)很快,但是有時(shí)候這個(gè)過(guò)程會(huì)很慢。
所以呢,還是盡量避免加載js的好。于是就引出來(lái)的“js文件的復(fù)用”。
更新js文件
Js文件更新了,但是瀏覽器卻還在用以前的js文件,因?yàn)橛芯彺媪?,而且還固執(zhí)的認(rèn)為緩存的js文件就是最新的,哎咋辦呀?
最簡(jiǎn)單的方法就是在加載js的時(shí)候,后面跟一個(gè)版本號(hào),有更新了,就版本號(hào)+1。比如 xxx.js?v=1。Js文件更新后就是 xxx.js?v=2。這樣js就肯定會(huì)被更新了。
看起來(lái)似乎很簡(jiǎn)單,但是這個(gè)版本號(hào)如何加上去?版本號(hào)本身又如何更新呢?
復(fù)用
這個(gè)就要先看看上面那個(gè)圖了,就是頁(yè)面結(jié)構(gòu),有一個(gè)外殼頁(yè)(或者首頁(yè)),我們叫做父頁(yè)。里面還有若干個(gè)iframe加載的頁(yè)面,我們加做子頁(yè)。
一般的做法是,父頁(yè)里加載jQuery.js,然后子頁(yè)里也要加載jQuery.js。當(dāng)然當(dāng)子頁(yè)在加載jQuery.js的時(shí)候,直接從緩存里面提取,一般不會(huì)再去折騰服務(wù)器了。
但是,既然父頁(yè)里面已經(jīng)加載了,子頁(yè)為啥還要再加載一次?直接用父頁(yè)里加載好的行不行呢?到網(wǎng)上搜了一下,似乎沒(méi)有人這么做。也許是我太另類了吧,我就是想實(shí)現(xiàn)這個(gè)方法。優(yōu)點(diǎn)就是,所有的js文件都在父頁(yè)里加載,子頁(yè)直接使用父頁(yè)里加載好的js,這樣子頁(yè)就不需要在折騰js文件了。這樣效率也可以更高一些,畢竟即使用緩存里加載,也是要判斷一下,然后在做個(gè)加載的動(dòng)作,還是會(huì)有一點(diǎn)點(diǎn)損耗,js文件越多也就越明顯。
那么如何實(shí)現(xiàn)呢,想想似乎很簡(jiǎn)單。
父頁(yè)里使用jQuery
Var aa = $('div'); //找到父頁(yè)里的所有div
子頁(yè)里是不是可以這么做?
Var bb = top.$ ('div') ; //能夠找到div,但是不是子頁(yè)的div而是父頁(yè)里的div。
咋回事呢?原因就在于搜索范圍。jQuery是有三個(gè)參數(shù)的,我們平時(shí)只用了第一個(gè),后面的就被忽略了。那么第二個(gè)參數(shù)是啥呢?就是搜索范圍。沒(méi)有指定的時(shí)候,jQuery會(huì)在哪里搜索呢?加載jQuery的頁(yè)面里面搜索,而不是調(diào)用$的頁(yè)面里搜索。
解決方法也很簡(jiǎn)單,加個(gè)參數(shù)就好了
Var bb = top.$ ('div',document) ; //指定搜索范圍:子頁(yè)的document
等等,這個(gè)似乎很煩人,我們?cè)趯懩_本的時(shí)候,還要考慮一下,這個(gè)腳本是在父頁(yè)里執(zhí)行還是在子頁(yè)里執(zhí)行嗎?
好了,做一個(gè)簡(jiǎn)單的封裝,避免這個(gè)麻煩。子頁(yè)里寫個(gè)函數(shù)
function $ (p1){
return top.$ (p1,document);
}
好了,大功告成了嗎?當(dāng)然沒(méi)有!預(yù)知后事如何,請(qǐng)聽(tīng)下回分解。
ps:下集預(yù)告。就是具體的實(shí)現(xiàn)代碼,還有一些思路和想法,不知道大家還有啥想知道的沒(méi),有的話,歡迎在下面回復(fù)一下。謝謝先。
相關(guān)文章
微信小程序?qū)崿F(xiàn)登錄頁(yè)云層漂浮的動(dòng)畫效果
微信小程序目前的火熱程度相信不用多言,最近利用空余時(shí)間用小程序?qū)崿F(xiàn)了個(gè)動(dòng)態(tài)的登錄頁(yè)效果,所以下面這篇文章主要給大家介紹了利用微信小程序?qū)崿F(xiàn)登錄頁(yè)云層漂浮動(dòng)畫效果的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-05-05微信小程序中使用vant組件庫(kù)的超詳細(xì)圖文教程
說(shuō)到vant框架相信大家應(yīng)該并不陌生了吧,做過(guò)移動(dòng)端開發(fā)的小伙伴們應(yīng)該都知道它吧,下面這篇文章主要給大家介紹了關(guān)于微信小程序中使用vant組件庫(kù)的超詳細(xì)圖文教程,需要的朋友可以參考下2023-03-03JS實(shí)現(xiàn)簡(jiǎn)單Tab欄切換案例
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)簡(jiǎn)單Tab欄切換案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03詳解js如何優(yōu)雅處理后端返回的單元格數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了JavaScript如何優(yōu)雅處理后端返回的單元格數(shù)據(jù),文中的示例代碼講解詳細(xì),有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10JavaScript?雙位非運(yùn)算(~~?操作符)使用場(chǎng)景實(shí)例探索
本文為大家介紹JavaScript中雙位非運(yùn)算?~~,?~~?操作符是一個(gè)強(qiáng)大且經(jīng)常被忽視的特性,它提供了一種快速、簡(jiǎn)潔的方式來(lái)處理數(shù)字和執(zhí)行類型轉(zhuǎn)換,通??梢员挥糜跀?shù)學(xué)計(jì)算和類型轉(zhuǎn)換,我們先了解一下?~~?的基本概念和它的一些應(yīng)用場(chǎng)景2024-01-01使用pjax實(shí)現(xiàn)無(wú)刷新更改頁(yè)面url
pjax=pushState+ajax,相信用過(guò)github的同學(xué)都知道,github部分頁(yè)面采用了pjax這個(gè)項(xiàng)目來(lái)實(shí)現(xiàn)ajax無(wú)刷新加載的同時(shí)改變頁(yè)面url。一起來(lái)學(xué)習(xí)一下這個(gè)插件吧。2015-02-02JS組件Bootstrap Table使用實(shí)例分享
這篇文章主要為大家詳細(xì)介紹了JS組件Bootstrap Table分頁(yè)使用方法,具有一定的實(shí)用性,感興趣的小伙伴們可以參考一下2016-05-05