簡體   English   中英

為什么腳本不執行?

[英]Why didn't the script execute?

我正在嘗試制作一個使用AJAX刷新其內容,樣式和腳本的Web應用程序,因此該網站無需重新加載頁面即可更新所有內容。

所以發生的事情是,我首先獲取頁面,並且在加載頁面時,我使用ajax向服務器發出請求並獲取html內容,然后再次請求獲取樣式,最后再次請求獲取腳本並將其放入腳本標簽

<script> //The script goes here </script>

然后,我將script標簽放在html內容的末尾,並用內容完全更新正文

<body>
  The HTML content goes here
  <script> //and here is the script </script>
</body>

請求成功且內容已加載,因此樣式和樣式以及當我使用瀏覽器檢查器工具時,都可以看到腳本標簽中加載的腳本,但腳本未執行。

這是問題的概述,您可以在這里查看代碼https://codepen.io/Yousef-Essam/project/editor/ZJGxea

app.js提供index.html文件,然后索引文件獲取script.js文件,該文件使用ajax發送兩個請求以獲取content.html文件和content.js文件,並將link標簽的href屬性設置為style文件。 然后將content.js文件放入帶有新內容的腳本標簽中。 盡管加載了content.html和樣式文件,並且腳本已加載到script標記中,但腳本未執行。

為什么會發生這種情況,我該如何解決?

--Update--

問題可能出在使用innerHTML上,但是為什么不真正起作用。

另外,我認為eval可能是一個解決方案,但由於不建議使用eval,因此我希望有一個更好的解決方案

這太長了,無法發布為評論,因此我將其作為答案發布。

您正確地注意到:

我認為eval可能是一個解決方案,但由於不建議使用eval,因此我希望有一個更好的解決方案

實際上,eval在任何語言中都是有問題的,因為它本質上允許正在運行的程序將字符串視為代碼。 這樣做的最大問題是,這為代碼注入打開了大門(用外行的術語:黑客攻擊)。 但是,此建議更多是理論建議,而不是有關使用什么功能的建議。

那么,該建議對eval意味着什么?

Eval是任何允許將字符串解釋為代碼的函數或機制。 不同的語言具有不同的功能或特性,可以進行eval 例如,某些語言允許遞歸字符串插值。 一些語言具有稱為interp()的函數,該函數會生成一個子解釋器。 有些語言從字面上講有一個稱為eval()的函數。

JavaScript具有四種評估機制:

  1. 使用eval()函數。

    • 傳遞給eval()任何字符串均視為代碼。
  2. 設置腳本標簽的src屬性

    • 假設src屬性的值是要下載的javascript文件
    • 這可以在文字代碼(HTML本身的實際代碼)或動態生成的腳本標記(在javascript中創建腳本元素並將其設置為src屬性)中使用
  3. 腳本標簽的正文

    • 腳本標簽內的任何文本均視為代碼
    • 這僅適用於文字代碼。 如您innerHTML ,禁止使用innerHTML設置腳本主體(自Netscape 4-第一個使用javascript的瀏覽器以來,此設置已被禁止)
  4. javascript: URI協議

    • :之后的所有內容均視為代碼
    • 僅在用戶單擊鏈接時有效

因此,您想要做的是執行eval 無論您是否使用eval函數都無所謂,您仍在嘗試使用innerHTML進行eval (盡管它不起作用)

因此,如果所有內容都是eval ,是否有一種在頁面上運行javascript的安全方法?

有-至少對於現代瀏覽器而言。

現代瀏覽器實現了一種稱為子資源完整性的功能。 不幸的是,在編寫此答案時,Edge不支持它。 基本上,您可以計算js文件的哈希值(例如sha1),並在script標簽中對其進行聲明,以便瀏覽器可以確認js文件未被篡改。 以下是一個示例:

<script src="https://cdn.example.com/script.js"
 integrity="sha384-+/M6kredJcxdsqkczBUjMLvqyHb1K/JThDXWsBVxMEeZHEaMKEOEct339VItX1zB"></script>

你這個偏執狂嗎?

這取決於。 eval問題對您可能真的很重要。 如果是這樣,從設置了子資源完整性的外部源加載javascript 是執行javascript的唯一安全方法

但並非每個人都如此偏執。 到目前為止,我們通常在沒有此功能的情況下做得很好。 以下是一些經驗法則,無論您使用script標記還是調用eval() ,它們都可以緩解代碼泄漏:

  1. 始終確保您僅執行靜態javascript代碼。 不要嘗試從字符串構造代碼。

  2. 如果必須從字符串構造代碼(例如,使用模板語言(如Handlebars)或使用捆綁程序(如Webpack或Browserify)),則切勿在代碼中包含任何用戶生成的內容。 您仍然可以通過發出ajax請求而不是將其包含在代碼中來加載內容。

  3. 如果必須在代碼中包含用戶生成的內容,請確保對內容進行清理。 有幾種普遍接受的策略,例如禁止使用特殊字符(如<>"或轉義特殊字符。甚至還有庫都可以為您做到這一點)。

基本上,我們要避免的情況是用戶輸入他們的名字為John"; console.log("gotcha");" 以及能夠執行代碼的方式。

HTML規范不允許解析使用innerHTML在頁面加載后動態添加為HTML標簽的SCRIPT元素(按照生活標准中text屬性描述下的注釋 )。

因此,在不使用eval來解析腳本的情況下,類似問題的答案在一次簡單的搜索中並不明顯-盡管它們可能存在,但我只看到了場外展示的替代技術。

這是一個不使用eval的動態加載器。 因為加載腳本是異步的,所以它使用( err, data )類型的回調函數來指示何時可以調用腳本。

function loadScript( url, callback) {
    var el = document.createElement("SCRIPT");
    el.type = "text/javascript";
    function finish( err) {
        callback( err, err ? false : true);
    }
    el.onerror = finish;
    if( el.readyState){  // <= IE 10
        el.onreadystatechange = function(){
            if( this.readyState == "complete"){
                finish( null);
            }
        };
    }
    else { 
        el.onload = function() { finish(null) };
    }
    el.setAttribute("async", true);
    el.src = url;
    document.getElementsByTagName("HEAD")[0].appendChild( el);
} 

// example call to load jQuery 3.2.1         

loadScript( "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js",
   function (err, ok) {
       if( err) {
           console.log( "loading failed: " + err);
        }
        else {
         console.log( "loading success");
        }
    }
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM