移動項目開發筆記(改變頁面JavaScript載入時的執行順序(zt))

來源:互聯網
上載者:User
文章目錄
  • 一、在HTML中嵌入Javasript的方法
  • 二、Javascript在頁面的執行順序
  • 三、如何改變Javascript在頁面的執行順序

     項目中由於通過後台代碼向用戶端多次註冊指令碼,如使用者控制項需要某些指令碼註冊,頁面也通過指令碼註冊彈出提示對話方塊,有時候我們需要這樣的需求:註冊指令碼的順序是我們JavaScript執行的順序,通過用ScriptManager.RegisterStartScript或RegisterClientScriptBlock註冊。不過這樣註冊的話,頁面的註冊順序不一定是頁面的執行順序。這樣可能達不到我們想要的效果:

(參考MSDN如下:)

RegisterClientScriptBlock 方法可在頁面中的

<form>

" sdata="langKeyword"><form> 開始標記之後添加一個指令碼塊。不能保證按照指令碼塊的註冊順序輸出這些指令碼塊。如果指令碼塊的順序很重要,請將指令碼塊串連到一個字串中(例如使用 StringBuilder 對象),然後將它們作為一個用戶端指令碼塊進行註冊。

 

RegisterStartupScript 方法所呈現的指令碼塊會在頁面完成載入之時、但頁面的用戶端 onload 事件引發之前執行。啟動指令碼塊位於呈現的 ASP.NET 頁面底部的

</form>

" sdata="langKeyword"></form> 標記之前,不能保證使用 RegisterStartupScript 註冊的啟動指令碼塊按照其註冊順序輸出。如果啟動指令碼塊的順序很重要,請使用 StringBuilder 對象將指令碼塊集中到一個字串中,然後將它們作為單個啟動指令碼進行註冊。

這樣我們需要用到Script的defer屬性:<Script type="text/javascript" defer="true">......</Script>

預設值為defer=false,這個屬性是表示其中的代碼是執行在其他指令碼之後。這樣就可以避免有些情況下對象為null的錯誤,而且也能達到我們的要求。通過對defer屬性的學習,對這個屬性有了更進一步的瞭解。下面是轉載的一篇文章,個人感覺比較實用,非常感謝原作者無私奉獻的精神。謝謝!

 

一、在HTML中嵌入Javasript的方法
  1. 直接在Javascript代碼放在標記對<script>和</script>之間
  2. 由<script />標記的src屬性制定外部的js檔案
  3. 放在事件處理常式中,比如:<p onclick="alert('我是由onclick事件執行的Javascript')">點擊我</p>
  4. 作為URL的主體,這個URL使用特殊的Javascript:協議,比如:<a href="javascript:alert('我是由javascript:協議執行的javascript')">點擊我</a>
  5. 利用javascript本身的document.write()方法寫入新的javascript代碼
  6. 利用Ajax非同步擷取javascript代碼,然後執行

第3種和第4種方法寫入的Javascript需要觸發才能執行,所以除非特別設定,否則頁面載入時不會執行。

 

二、Javascript在頁面的執行順序
  1. 頁面上的Javascript代碼是HTML文檔的一部分,所以Javascript在頁面裝載時執行的順序就是其引入標記<script />的出現順序, <script />標記裡面的或者通過src引入的外部JS,都是按照其語句出現的順序執行,而且執行過程是文檔裝載的一部分。
  2. 每個指令碼定義的全域變數和函數,都可以被後面執行的指令碼所調用。
  3. 變數的調用,必須是前面已經聲明,否則擷取的變數值是undefined。
Code
<script type="text/javscrpt">//<![CDATA[
alert(tmp);  //輸出 undefined
var tmp = 1;
alert(tmp);  //輸出 1
//]]></script>

 

4.同一段指令碼,函數定義可以出現在函數調用的後面,但是如果是分別在兩段代碼,且函數調用在第一段代碼中,則會報函數未定義錯誤。 

Code
<script type="text/javscrpt">//<![CDATA[
aa();            //瀏覽器報錯
//]]></script>
<script type="text/javscrpt">//<![CDATA[
aa();            //輸出 1 
function aa(){alert(1);}
//]]></script>

5.document.write()會把輸出寫入到指令碼文檔所在的位置,瀏覽器解析完documemt.write()所在文檔內容後,繼續解析document.write()輸出的內容,然後在繼續解析HTML文檔。

Code
<script type="text/javascript">//<![CDATA[
    document.write('<script type="text/javascript" src="test.js"><\/script>');
    document.write('<script type="text/javascript">');
    document.write('alert(2);')
    document.write('alert("我是" + tmpStr);');
    document.write('<\/script>');
    //]]></script>
  <script type="text/javascript">//<![CDATA[
    alert(3);
    //]]></script>

test.js的內容是:

var tmpStr = 1;
alert(tmpStr);

  • 在Firefox和Opera中的彈出值的順序是:1、2、我是1、3
  • 在IE中彈出值的順序是:2、1、3,同時瀏覽器報錯:tmpStr未定義

原因可能是IE在document.write時,並未等待載入SRC中的Javascript代碼完畢後,才執行下一行,所以導致2先彈出,並且執行到document.write(’document.write("我是" + tmpStr)’)調用tmpStr時,tmpStr並未定義,從而報錯。

解決這個問題,可以利用HTML解析是解析完一個HTML標籤,再執行下一個的原理,把代碼拆分來實現:

Code
<script type="text/javascript">//<![CDATA[
    document.write('<script type="text/javascript" src="test.js"><\/script>');
    //]]></script>
  <script type="text/javascript">//<![CDATA[
    document.write('<script type="text/javascript">');
    document.write('alert(2);')
    document.write('alert("我是" + tmpStr);');
    document.write('<\/script>');
    //]]></script>
  <script type="text/javascript">//<![CDATA[
    alert(3);
    //]]></script>

這樣IE下和其他瀏覽器輸出值的順序都是一直的了:1、2、我是1、3。

 

三、如何改變Javascript在頁面的執行順序
  1. 利用onload
Code
<script type="text/javascript">//<![CDATA[
window.onload = f;
function f(){alert(1);}
alert(2);
//]]></script>

輸出值順序是 2、1。

需要注意的是,如果存在多個winodws.onload的話,只有最有一個生效,解決這個辦法是:

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

   2.利用2級DOM事件類型

Code
if(document.addEventListener){
window.addEventListener('load',f,false);
window.addEventListener('load',f1,false);

}else{
window.attachEvent('onload',f);
window.attachEvent('onload',f1);

}

 3.IE中可以利用defer,defer作用是把代碼載入下來,並不立即執行,等文檔裝載完畢之後再執行,有點類似window.onload,但是沒有window.onload那樣的局限性,可以重複使用,但是只在IE中有效,所以上面的例子可以修改成為

Code
<script type="text/javascript">//<![CDATA[
document.write('<script type="text/javascript" src="test.js"><\/script>');
document.write('<script type="text/javascript" defer="defer">');
document.write('alert(2);')
document.write('alert("我是" + tmpStr);');
document.write('<\/script>');
//]]></script>
<script type="text/javascript">//<![CDATA[
alert(3);
//]]></script>

這樣IE就不報錯了,輸出值的順序變成:1、3、2、我是1

當HTML解析器遇到一個指令碼,它必須按常規終止對文檔的解析並等待指令碼執行。為瞭解決這個問題HTML4標準定義了defer。通過defer來提示瀏覽器可以繼續解析HTML文檔,並順延強制指令碼。這種延遲在指令碼從外部檔案載入時非常有用,讓瀏覽器不必等待外部檔案全部載入之後才繼續執行,能有效提高效能。IE是目前唯一支援defer屬性的瀏覽器,但IE並沒有正確的實現了defer屬性,因為延遲的指令碼總是被延遲,直到文檔結束,而不是只延遲到下一個非延遲的指令碼。這意味著,IE中延遲的指令碼的執行順序相當混亂,並且不能定義任何後面非延遲指令碼並須的函數和變數。在IE中所有的defer的指令碼執行時間應該都是HTML文檔樹建立以後,window.onload之前。

4.利用Ajax。
因為xmlhttpRequest能判斷外部文檔載入的狀態,所以能夠改變代碼的載入順序。

 

原文地址:Javascript在頁面載入時的執行順序

再次感謝原作者。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.