解決window.onload延遲加載問題


window.onload方法,表示當頁面所有的元素都加載完畢,並且所有要請求的資源也加載完畢才觸發執行function這個匿名函數里邊的具體內容。這樣肯定保證了代碼在domReady之后執行。使用window.onload方法在文檔外部資源不多的情況下不會有什么問題,但是當頁面中有大量遠程圖片或要請求的遠程資源時,我們需要讓js在點擊每張圖片時,進行相應的操作,如果此時外部資源還沒有加載完畢,點擊圖片是不會有任何反應的,大大降低了用戶體驗。那既然window.onload方法不可行,又該怎么做呢?

你肯定想到了jquery中的$(document).ready(function(){})方法了,其實jquery中的domReady應該和window.onload的實現原理是大同小異的。為了解決window.onload的短板,w3c 新增了一個 DOMContentLoaded 事件。

 

(1)onload實現

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script>
        window.onload=function(){
            document.getElementById("header").style.color="red";
        }
    </script>
</head>
<body>
    <h1 id="header">我是H1</h1>
    <img src="1.jpg" alt="">
    <img src="1.jpg" alt="">
    <img src="1.jpg" alt="">
    <!-- 如果大量圖片的時候onload需要等待全部加載完成才能將h1標簽給渲染成紅色 -->
</body>
</html>

(2)Jquery解決以上問題

$(document).ready()方法和window.onload有什么區別?

(1)、window.onload方法是在網頁中所有的元素(包括元素的所有關聯文件)完全加載到瀏覽器后才執行的。

(2)、$(document).ready() 方法可以在DOM包括圖片載入就緒時就對其進行操縱,並調用執行綁定的函數。

tip:jquery就是調用了原生JS事件DOMContentLoaded 來實現相同功能

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="jquery.js"></script>
    <script>
        $(document).ready(function(){
            document.getElementById("header").style.color="red";
        })
    </script>
</head>
<body>
    <h1 id="header">我是H1</h1>
    <img src="1.jpg" alt="">
    <img src="1.jpg" alt="">
    <img src="1.jpg" alt="">
    <!-- 假設大量遠程圖片正在加載 -->
</body>
</html>

(3)原生JS事件DOMContentLoaded實現

參考jquery中domReady的實現原理,來看一下javascript中domReady的實現策略。

JavaScript實現domReady功能,【domReady.js】兼容各瀏覽器通用版本的源代碼:

function myReady(fn){  
    //對於現代瀏覽器,對DOMContentLoaded事件的處理采用標准的事件綁定方式  
    if ( document.addEventListener ) {  
        document.addEventListener("DOMContentLoaded", fn, false);  
    } else {  
        IEContentLoaded(fn);  
    }  
    //IE模擬DOMContentLoaded  
    function IEContentLoaded (fn) {  
        var d = window.document;  
        var done = false;  
  
        //只執行一次用戶的回調函數init()  
        var init = function () {  
            if (!done) {  
                done = true;  
                fn();  
            }  
        };  
        (function () {  
            try {  
                // DOM樹未創建完之前調用doScroll會拋出錯誤  
                d.documentElement.doScroll('left');  
            } catch (e) {  
                //延遲再試一次~  
                setTimeout(arguments.callee, 50);  
                return;  
            }  
            // 沒有錯誤就表示DOM樹創建完畢,然后立馬執行用戶回調  
            init();  
        })();  
        //監聽document的加載狀態  
        d.onreadystatechange = function() {  
            // 如果用戶是在domReady之后綁定的函數,就立馬執行  
            if (d.readyState == 'complete') {  
                d.onreadystatechange = null;  
                init();  
            }  
        }  
    }  
}  

粘貼上面代碼到新js文件保存。在頁面中引入domReady.js文件,引用myReady(回調函數)方法即可。

用原生JS實現跟Jquery的ready相同功能效果:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="domReady.js"></script>  <!--引用domReady功能 -->
    <script>
        myReady(function(){
            document.getElementById("header").style.color="red";
        })
    </script>
</head>
<body>
    <h1 id="header">我是H1</h1>
    <img src="1.jpg" alt="">
    <img src="1.jpg" alt="">
    <img src="1.jpg" alt="">
    <!-- 假設大量遠程圖片正在加載 -->
</body>
</html>

 很明顯,onload事件是要在所有請求都完成之后才執行,而domReady利用hack技術,在加載完dom樹之后就能執行,所以domReady比onload執行時間更早,建議采用domReady。

(4)domReady與window.onload延遲差距測試

下面通過一個案例,來比較domReady與window.onload實現的不同,很明顯,onload事件是要在所有請求都完成之后才執行,而domReady利用hack技術,在加載完dom樹之后就能執行,所以domReady比onload執行時間更早,建議采用domReady。

    <!DOCTYPE html>
    <html lang="zh-CN">

    <head>
        <meta charset="utf-8">
        <title>domReady與window.onload</title>
        <script src="domReady.js"></script>
    </head>

    <body>
        <div id="showMsg"></div>
        <div>
            <img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zofelhdj20xc0xc42s.jpg" alt="">
            <img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zofahw3j20m80etq4a.jpg" alt="">
            <img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zoi3ny6j20l20dw4gd.jpg" alt="">
            <img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zog3tauj20m80et0uw.jpg" alt="">
            <img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zofi2o5j20m80ettaq.jpg" alt="">
            <img src="http://ww1.sinaimg.cn/large/ae49ba57gy1fe9zohjuvhj20tb0cdwvp.jpg" alt="">
        </div>
        <script>
        var d = document;
        var msgBox = d.getElementById("showMsg");
        var imgs = d.getElementsByTagName("img");
        var time1 = null,
            time2 = null;
        myReady(function() {
            msgBox.innerHTML += "dom已加載!<br>";
            time1 = new Date().getTime();
            msgBox.innerHTML += "時間戳:" + time1 + "<br>";
        });
        window.onload = function() {
            msgBox.innerHTML += "onload已加載!<br>";
            time2 = new Date().getTime();
            msgBox.innerHTML += "時間戳:" + time2 + "<br>";
            msgBox.innerHTML += "domReady比onload快:" + (time2 - time1) + "ms<br>";
        };
        </script>
    </body>

    </html>

執行結果對比,發現DomReady比onload快樂2秒左右。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM