国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > JavaScript > 正文

Javascript封裝DOMContentLoaded事件實(shí)例

2019-11-20 14:29:46
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

最近在寫(xiě)一個(gè)Javascript的框架,剛把DOMContentLoaded事件封裝好,略帶小興奮,把開(kāi)發(fā)過(guò)程中遇到的原理和兼容性問(wèn)題做篇筆記,省的忘記到處找。

我們?cè)趯?xiě)js代碼的時(shí)候,一般都會(huì)添加window.onload事件,主要是為了在DOM加載完后可以使用getElementById,getElementsByTagName等方法選取DOM元素進(jìn)行操作,但是window.load會(huì)等到加載完DOM、腳本、CSS,最后加載完圖片甚至是iframe中的所有資源才會(huì)觸發(fā),很多時(shí)候網(wǎng)頁(yè)的圖片較多較大,要等最后圖片這個(gè)耗時(shí)大戶(hù)加載完才執(zhí)行js明顯有些太遲了,很多時(shí)候都會(huì)影響用戶(hù)體驗(yàn)。

很多js框架都有個(gè)document.ready的功能,像JQuery的$(document).ready()方法,可以在DOM加載完就立即執(zhí)行js代碼,讓圖片自個(gè)慢慢加載吧。

document.ready的核心是DOMContentLoaded事件,firefox、chrome、opera、safari、ie9+都可以使用addEventListener(‘DOMContentLoaded',fn,false)進(jìn)行事件綁定,而ie6~8不支持DOMContentLoaded事件,所以要針對(duì)ie6~8做兼容性處理。

資料上說(shuō)ie6~8可以使用document.onreadystatechange事件監(jiān)聽(tīng)document.readyState狀態(tài)是否等于complete來(lái)判斷DOM是否加載完畢,如果頁(yè)面中嵌有iframe的話(huà),ie6~8的document.readyState會(huì)等到iframe中的所有資源加載完才會(huì)變成complete,此時(shí)iframe變成了耗時(shí)大戶(hù)。但是經(jīng)過(guò)測(cè)試,即使頁(yè)面中沒(méi)有iframe,當(dāng)readyState等于complete時(shí),實(shí)際觸發(fā)的是onload事件而不是DOMContentLoaded事件,對(duì)這點(diǎn)表示驚奇。

還好ie有個(gè)特有的doScroll方法,當(dāng)頁(yè)面DOM未加載完成時(shí),調(diào)用doScroll方法時(shí),就會(huì)報(bào)錯(cuò),反過(guò)來(lái),只要一直間隔調(diào)用doScroll直到不報(bào)錯(cuò),那就表示頁(yè)面DOM加載完畢了,不管圖片和iframe中的內(nèi)容是否加載完畢,此法都有效。

如果有多個(gè)js文件綁定了document.ready事件,為了防止瀏覽器重復(fù)綁定,同時(shí)有序執(zhí)行,可以引入一個(gè)事件隊(duì)列機(jī)制來(lái)解決。

以上就是document.ready事件的原理和兼容性問(wèn)題,下面貼段實(shí)例代碼,為了方便理解執(zhí)行過(guò)程,使用函數(shù)封裝的模式,執(zhí)行過(guò)程都寫(xiě)在注釋里了,如果有不妥之處歡迎指教。

復(fù)制代碼 代碼如下:

//保存domReady的事件隊(duì)列
eventQueue = [];

//判斷DOM是否加載完畢
isReady = false;

//判斷DOMReady是否綁定
isBind = false;

/*執(zhí)行domReady()
 *
 *@param    {function}
 *@execute  將事件處理程序壓入事件隊(duì)列,并綁定DOMContentLoaded
 *          如果DOM加載已經(jīng)完成,則立即執(zhí)行
 *@caller
 */
function domReady(fn){
    if (isReady) {
        fn.call(window);
    }
    else{
        eventQueue.push(fn);
    };

    bindReady();
};

/*domReady事件綁定
 *
 *@param    null
 *@execute  現(xiàn)代瀏覽器通過(guò)addEvListener綁定DOMContentLoaded,包括ie9+
            ie6-8通過(guò)判斷doScroll判斷DOM是否加載完畢
 *@caller   domReady()
 */
function bindReady(){
    if (isReady) return;
    if (isBind) return;
    isBind = true;

    if (window.addEventListener) {
        document.addEventListener('DOMContentLoaded',execFn,false);
    }
    else if (window.attachEvent) {
        doScroll();
    };
};

/*doScroll判斷ie6-8的DOM是否加載完成
 *
 *@param    null
 *@execute  doScroll判斷DOM是否加載完成
 *@caller   bindReady()
 */
function doScroll(){
    try{
        document.documentElement.doScroll('left');
    }
    catch(error){
        return setTimeout(doScroll,20);
    };
    execFn();
};

/*執(zhí)行事件隊(duì)列
 *
 *@param    null
 *@execute  循環(huán)執(zhí)行隊(duì)列中的事件處理程序
 *@caller   bindReady()
 */
function execFn(){
    if (!isReady) {
        isReady = true;
        for (var i = 0; i < eventQueue.length; i++) {
            eventQueue[i].call(window);
        };
        eventQueue = [];
    };
};

//js文件1
domReady(function(){
    ...
});
//js文件2
domReady(function(){
    ...
});

//注意,如果是異步加載的js就不要綁定domReady方法,不然函數(shù)不會(huì)執(zhí)行,
//因?yàn)楫惒郊虞d的js下載之前,DOMContentLoaded已經(jīng)觸發(fā),addEventListener執(zhí)行時(shí)已經(jīng)監(jiān)聽(tīng)不到了

測(cè)試頁(yè)面:都加載了兩張很大的圖片,onload需要圖片加載完才能執(zhí)行js,DOMContentLoaded只需等到DOM加載完即可執(zhí)行js。可以打開(kāi)firebug查看加載過(guò)程,每次測(cè)試前記得先清理下瀏覽器緩存。

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 墨竹工卡县| 临沂市| 闵行区| 莲花县| 兖州市| 元谋县| 平乡县| 通州市| 青神县| 德庆县| 湖南省| 新和县| 原平市| 临夏县| 成武县| 江津市| 朝阳县| 道孚县| 昌平区| 郁南县| 镇赉县| 儋州市| 荃湾区| 望都县| 东方市| 綦江县| 靖安县| 遵化市| 永和县| 日照市| 三江| 楚雄市| 南江县| 晋江市| 长治县| 当阳市| 荣成市| 简阳市| 磴口县| 田林县| 仁化县|