從一個例子了解window.onload、$(function(){})、$(window).load(function(){})的加載順序


最近遇到一個輪播需求

1. ajax請求服務器,返回json,判斷json數據里每一項中isFix屬性是0還是1,0表示不輪播,1表示需要輪播。

2. 當isFix屬性為0的時候,表示該圖片不輪播,相反,isFix為1的時候,表示該圖片需要輪播

3. 屏幕最多容納6個圖片,並且每個圖片都有邊距。不固定高度,自適應寬度。

4. 不輪播的圖片固定在左邊,輪播的圖片需要在右邊輪播,每次輪播的距離為一張圖片的寬度和間距

5. 圖片寬高不固定,反正一行最多6個。

6. 兼容IE8

我的思路是:

1. ajax請求的時候,分兩次把輪播和不輪播的圖片append到100%寬度的div中,

2. 從要輪播圖片的第一張開始到最后一張,把這些圖片append到100%減去不輪播圖片所占據的寬度的div中

3. 最后再用margin-left來實現輪播效果。

實現的效果:

總共10個圖片,請求到的數據是其中三個不輪播,剩下7個輪播,由於一行只能顯示6個,所以顯示的應該是3個在輪播。

 

在實現的過程中,我需要去獲取裝輪播圖div的高度。而獲取高度肯定需要在圖片加載完才能正確獲取到,所以我選擇了在window.onload=function(){} 操作獲取圖片高度。

然而,遇到了如下的問題:

第一個問題:第一次運行程序時竟然不執行window.onload里面的內容???why???

產生原因:不管是外鏈js還是頁面中的js,所有的window.onload=function(){}都只有一個且是最后一個生效后面的會覆蓋前面的。我其它js文件里有window.onload,而這個輪播的js文件要比另一個先引入,所以這個不執行。

解決辦法:既然只能有一個window.onload,那么我換成$(window).load(function (){})不就行了嗎?真機智。。。。。。

 

第二個問題:換成$(window).load(function (){})之后,在其它瀏覽器中能正確獲取高度,而在火狐瀏覽器中,有時候能獲取到高度,有時候卻給我返回null。。。???這又是什么鬼

產生原因:返回null,說明並沒有找到該元素。而ajax請求是異步,意思就是在請求成功之前,還能執行下面的代碼。所以在ajax請求成功,把圖片append到div中之前就已經執行到獲取高度的js代碼了。

解決辦法:把ajax的async屬性設置為false即同步請求數據。啊。。。。。。真個世界清靜了。

為了防止ajax同步請求時不能執行下面的js,所以我把這個js文件放到最后,以免請求時間過長時,阻塞下面的js加載。。

 

總結:

  1. window.onload=function(){}是等待所有的內容都加載完之后執行,比如圖片,內容,js,css等。

  2. $(function(){}),是等待DOM加載完之后執行(我的理解是標簽繪制完畢之后),圖片未加載完時也能執行。

  3. $(function(){})是$(document).ready(function(){})的簡寫方式,功能是一樣的。

  4. $(window).load(function (){})也是等待所有的內容都加載完之后執行

  5. 不管是外鏈js還是頁面中的js的window.onload都只執行最后的一個

  6. $(window).load(function (){})可以有多個,而且都是順序執行

 

擴展:

如果要js實現多個window.onload的方式

1.在body中調用多個函數

<body onload="f1();f2();f3();">
</body>

   這種方式和下面這種方式是一樣的。

function f1(){...}
function f2(){...}
window.onload=function(){
    f1();
    f2();
}

   顯然,這種方式不太可取。畢竟不能把所有頁面的function都聚在一堆。

 

2. 判斷window.onload是否已經執行了一次,如果是的話,就把原來執行的window.onload函數按照方式1來處理。這樣就不會覆蓋了

function f1(){...}
function f2(){...}

function moreLoad(fn) {
    var winLoad = window.onload;
    if (typeof window.onload != 'function') {
        window.onload = fn;
    } else {
        window.onload = function() {
            winLoad ();
            fn();
        }
    }
}

moreLoad(f1)
moreLoad(f2)

 

 3. 采用事件監聽,ie8以及ie8以下為attachEvent,其它的為addEventListener。這樣也不會覆蓋

function f3(){
    alert("f3")
}
function f4(){
    alert("f4")
}
function win_load(callBack){
    if (window.attachEvent) {
        window.attachEvent("onload", callBack);
    } else if (window.addEventListener) {
        window.addEventListener("load", callBack);
    }
}
win_load(f3)
win_load(f4)

  注意:

    1.attachEvent的第二個參數,需要在事件前面加“on”,所以這里加載事件是onload  。而addEventListener第二個參數不用再事件前面加“on”,所以這里是load;本來還有第三個參數,可選,表示指定事件是否在捕獲或冒泡階段執行。默認為false,所以這里就不用寫上去。

    2. ie的attachEvent里面綁定多個事件的執行順序是不一樣的,如上面的例子,IE中是先執行f4函數,再執行f3函數,倒着執行的。而addEventListener是正常的

 

最后說一下加載順序:假如我在當前頁面引入了兩個js文件,一個a.js  一個b.js,分別都有window.onload$(function(){}) $(window).load(function (){})

執行的順序是:

  1. 先以a.js,b.js的順序執行a.js中未包含在window.onload與$(function(){})和$(window).load(function (){})中的代碼。

  2. 然后再執行$(function(){})里面的代碼,

  3. 然后以a.js,b.js的順序,執行$(window).load(function (){})里面的代碼,

  4. 最后執行最后一個js中window.onload里面的代碼 

  但是!!!在火狐和IE瀏覽器中,window.onload的執行順序要高於$(window).load(function (){}),其它瀏覽器的加載順序都是一樣的。這個我就理解不了了。。。。。。

  

 


免責聲明!

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



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