Thực thi các phần tử <script> được chèn bằng .innerHTML


111

Tôi có một tập lệnh chèn một số nội dung vào một phần tử bằng cách sử dụng innerHTML.

Ví dụ, nội dung có thể là:

<script type="text/javascript">alert('test');</script>
<strong>test</strong>

Vấn đề là mã bên trong <script>thẻ không được thực thi. Tôi đã tìm kiếm nó một chút nhưng không có giải pháp rõ ràng. Nếu tôi chèn nội dung bằng jQuery, $(element).append(content);các phần script sẽ có eval'd trước khi được đưa vào DOM.

Có ai có một đoạn mã thực thi tất cả các <script>phần tử không? Mã jQuery hơi phức tạp nên tôi thực sự không thể tìm ra cách nó được thực hiện.

Chỉnh sửa :

Bằng cách xem qua mã jQuery, tôi đã tìm ra cách jQuery thực hiện điều đó, dẫn đến đoạn mã sau:

Demo:
<div id="element"></div>

<script type="text/javascript">
  function insertAndExecute(id, text)
  {
    domelement = document.getElementById(id);
    domelement.innerHTML = text;
    var scripts = [];

    ret = domelement.childNodes;
    for ( var i = 0; ret[i]; i++ ) {
      if ( scripts && nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
            scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
        }
    }

    for(script in scripts)
    {
      evalScript(scripts[script]);
    }
  }
  function nodeName( elem, name ) {
    return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
  }
  function evalScript( elem ) {
    data = ( elem.text || elem.textContent || elem.innerHTML || "" );

    var head = document.getElementsByTagName("head")[0] || document.documentElement,
    script = document.createElement("script");
    script.type = "text/javascript";
    script.appendChild( document.createTextNode( data ) );
    head.insertBefore( script, head.firstChild );
    head.removeChild( script );

    if ( elem.parentNode ) {
        elem.parentNode.removeChild( elem );
    }
  }

  insertAndExecute("element", "<scri"+"pt type='text/javascript'>document.write('This text should appear as well.')</scr"+"ipt><strong>this text should also be inserted.</strong>");
</script>

1
Tại sao bạn không thể lặp lại các phần tử con của phần tử và đối với mỗi phần tử là phần tử script, bạn chỉ cần đánh giá () innerHtml của phần tử đó? Đây là cách tôi đã thấy nó được thực hiện bởi một nhà cung cấp thành phần lớn, mỗi khi họ hoàn thành một lệnh gọi lại ajax để thêm nội dung vào DOM, họ thực hiện chính xác điều đó. Hãy nhớ rằng nó có thể chậm, đặc biệt là trong IE7.
slugster

2
Andreas: Nếu tôi thêm một hàm, chẳng hạn như function testFunction(){ alert('test'); }mã được chèn vào innerHTML, rồi thử gọi nó, thì nó cho biết rằng hàm chưa được xác định.
phidah

1
Tuyệt vời phidah, hoạt động giống như sự quyến rũ, cổ vũ
Marcin

3
Tôi nghĩ rằng điều hoàn toàn quan trọng là phải hiểu rằng đây là hành vi dự kiến ​​của trình duyệt để ngăn chặn các cuộc tấn công tạo kịch bản chéo trang web. Nếu văn bản bạn đặt là innerHTML do Bob cung cấp, nó sẽ thực thi trên trình duyệt của Alice gây ra thiệt hại (hãy nghĩ đến một diễn đàn nơi mọi người có thể viết nhận xét bằng cách thêm các thẻ script vào chúng). Bạn có thể đọc thêm về nó tại đây: en.wikipedia.org/wiki/Cross-site_scripting . Hãy tiết kiệm!
Xatian

1
HTML đã thay đổi rất nhiều kể từ năm 2010. Những ngày này, có thể bạn muốn xem: stackoverflow.com/a/58862506/890357
marciowb

Câu trả lời:


27

Tập lệnh của OP không hoạt động trong IE 7. Với sự trợ giúp từ SO, đây là một tập lệnh thực hiện:

exec_body_scripts: function(body_el) {
  // Finds and executes scripts in a newly added element's body.
  // Needed since innerHTML does not run scripts.
  //
  // Argument body_el is an element in the dom.

  function nodeName(elem, name) {
    return elem.nodeName && elem.nodeName.toUpperCase() ===
              name.toUpperCase();
  };

  function evalScript(elem) {
    var data = (elem.text || elem.textContent || elem.innerHTML || "" ),
        head = document.getElementsByTagName("head")[0] ||
                  document.documentElement,
        script = document.createElement("script");

    script.type = "text/javascript";
    try {
      // doesn't work on ie...
      script.appendChild(document.createTextNode(data));      
    } catch(e) {
      // IE has funky script nodes
      script.text = data;
    }

    head.insertBefore(script, head.firstChild);
    head.removeChild(script);
  };

  // main section of function
  var scripts = [],
      script,
      children_nodes = body_el.childNodes,
      child,
      i;

  for (i = 0; children_nodes[i]; i++) {
    child = children_nodes[i];
    if (nodeName(child, "script" ) &&
      (!child.type || child.type.toLowerCase() === "text/javascript")) {
          scripts.push(child);
      }
  }

  for (i = 0; scripts[i]; i++) {
    script = scripts[i];
    if (script.parentNode) {script.parentNode.removeChild(script);}
    evalScript(scripts[i]);
  }
};

4
Sử dụng tốt hơn jQuery $(parent).html(code)- xem câu trả lời của tôi bên dưới.
iirekm

khi tập lệnh được đưa vào DOM, tôi nên xóa nó như thế nào?
S4beR

1
Tập lệnh không đệ quy, vì vậy sẽ chỉ xem xét các phần tử con trực tiếp. Điều này phù hợp với tôi:if (nodeName(child, "script" ) && (!child.type || child.type.toLowerCase() === "text/javascript")) { scripts.push(child); } else { exec_body_scripts(child); }
st4wik

2
Lưu ý rằng đoạn mã trên không thực thi các tập lệnh tải qua src. Tập lệnh trên có thể được thay đổi để kiểm tra elem.srcvà đặt thuộc srctính có điều kiện của phần tử tập lệnh đã tạo thay vì đặt nội dung văn bản của nó.
Ryan Morlok

Tại sao không sử dụng thủ thuật toàn cụceval thay vì tạo một <script>phần tử và chèn nó vào <head>? Cả hai đều thực thi mã JS mà không để lộ quá trình đóng hiện tại.
Finesse

31

@phidah ... Đây là một giải pháp rất thú vị cho vấn đề của bạn: http://24ways.org/2005/have-your-dom-and-script-it-too

Vì vậy, nó sẽ trông giống như sau:

<img src="empty.gif" onload="alert('test');this.parentNode.removeChild(this);" />


2
và thậm chí tốt hơn, không cần phải có một hình ảnh với "onerror" sự kiện, tốt đẹp cho tiêm XSS nhanh jvfconsulting.com/blog/47/... :)
baptx

11
Bạn có thể sử dụng <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" onload="alert('test');">nếu bạn muốn ngăn chặn một yêu cầu http vô ích.
Savas Vedova

1
yêu nó ! (đã thêm style="display:none;) để ẩn biểu tượng hình ảnh bị hỏng
kris

Trên thực tế, <style>tốt hơn là <img>vì nó không thực hiện yêu cầu mạng
lưu vực

23

Đây là một tập lệnh ngắn hơn, hiệu quả hơn cũng hoạt động cho các tập lệnh có thuộc srctính:

function insertAndExecute(id, text) {
    document.getElementById(id).innerHTML = text;
    var scripts = Array.prototype.slice.call(document.getElementById(id).getElementsByTagName("script"));
    for (var i = 0; i < scripts.length; i++) {
        if (scripts[i].src != "") {
            var tag = document.createElement("script");
            tag.src = scripts[i].src;
            document.getElementsByTagName("head")[0].appendChild(tag);
        }
        else {
            eval(scripts[i].innerHTML);
        }
    }
}

Lưu ý: trong khi evalcó thể gây ra một lỗ hổng bảo mật nếu không được sử dụng đúng cách, nó là nhiều nhanh hơn so với việc tạo ra một thẻ script khi đang bay.


1
điều này đã giúp tôi nhưng tôi cảm thấy bẩn khi sử dụng eval. đảm bảo văn bản không thể bị xâm phạm, tôi không thấy lỗ hổng.
John

@ random-user evalđược thiết kế để làm tổn thương người dùng. Bất kỳ quá trình thực thi tập lệnh động nào đều là rủi ro và đây là lý do tại sao CSP gọi 'unsafe-eval'nó là như vậy. Bạn cũng đang làm tổn hại đến tính bảo mật của các trang web của mình nếu bạn đang sử dụng nó trong thư viện vì họ không thể tắt nó đi.
jonathanKingston

Việc kiểm tra điều này trong Chrome 44 gây ra vòng lặp vô hạn khi appendChild được gọi vì điều này làm tăng giá trị scripts.length.
Codewithcheese

4
Các tập lệnh có thuộc srctính sẽ được tải xuống không đồng bộ và được thực thi khi đến nơi. Thứ tự không được bảo toàn. Các tập lệnh nội tuyến cũng sẽ được thực thi không theo thứ tự, đồng bộ trước các tập lệnh không đồng bộ.
robert

21

Bạn không nên sử dụng thuộc tính innerHTML mà thay vào đó là phương thức appendChild của Node: một nút trong cây tài liệu [HTML DOM]. Bằng cách này, bạn có thể gọi mã đã nhập của mình sau này.

Đảm bảo rằng bạn hiểu rằng node.innerHTML không giống như node.appendChild . Bạn có thể muốn dành chút thời gian trên Tham chiếu ứng dụng khách Javascript để biết thêm chi tiết và DOM. Hy vọng những điều sau đây sẽ giúp ...

Công việc tiêm mẫu:

<html>
<head>
<title>test</title>
<script language="javascript" type="text/javascript">
    function doOnLoad(){
        addScript('inject',"function foo(){ alert('injected'); }");
    }


    function addScript(inject,code){
        var _in = document.getElementById('inject');
        var scriptNode = document.createElement('script');
        scriptNode.innerHTML = code;
        _in.appendChild(scriptNode);
    }

</script>
</head>
<body onload="doOnLoad();">
    <div id="header">some content</div>
    <div id="inject"></div>
    <input type="button" onclick="foo(); return false;" value="Test Injected" />
</body>
</html>

Trân trọng,


2
Cuối cùng là một người thực sự giải thích một chút về vấn đề này hơn là tất cả các try this, look how clever I amcâu trả lời khác . Xứng đáng với tia cực tím, nó có của tôi.
RiggsFolly

tôi uv cái này vì nó là cách đơn giản nhất để tiêm mã javascript thực thi sau khi tiêm. Tôi chỉ không hiểu sự khác biệt giữa việc thêm với innerHTML không thực thi và cách ở trên với appendChild thực thi. Tôi đã sử dụng điều này thành công để tạo một trang động có tập lệnh từ đầu với socket.io
Wetlip

2
var _in = document.getElementById(inject);, Tôi nghĩ.
Ron Burk

21

Phiên bản ES6 đơn giản của câu trả lời của @ joshcomley với một ví dụ.

Không có JQuery, Không có thư viện, Không có eval, Không thay đổi DOM, Chỉ là Javascript thuần túy.

http://plnkr.co/edit/MMegiu?p=preview

var setInnerHTML = function(elm, html) {
  elm.innerHTML = html;
  Array.from(elm.querySelectorAll("script")).forEach( oldScript => {
    const newScript = document.createElement("script");
    Array.from(oldScript.attributes)
      .forEach( attr => newScript.setAttribute(attr.name, attr.value) );
    newScript.appendChild(document.createTextNode(oldScript.innerHTML));
    oldScript.parentNode.replaceChild(newScript, oldScript);
  });
}

Sử dụng

$0.innerHTML = HTML;    // does *NOT* run <script> tags in HTML
setInnerHTML($0, HTML); // does run <script> tags in HTML

1
typo: tên của hàm là setInnerHtmlkhôngsetInnerHTML
Pery Mimon

Lưu ý rằng trong plnkr được liên kết, tên hàm là setInnerHTMLnhưng nó đang được gọi setInnerHtmltừ bên trong runBhàm. Do đó ví dụ không hoạt động
danbars

16

Hãy thử đoạn mã này:

function stripAndExecuteScript(text) {
    var scripts = '';
    var cleaned = text.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
        scripts += arguments[1] + '\n';
        return '';
    });

    if (window.execScript){
        window.execScript(scripts);
    } else {
        var head = document.getElementsByTagName('head')[0];
        var scriptElement = document.createElement('script');
        scriptElement.setAttribute('type', 'text/javascript');
        scriptElement.innerText = scripts;
        head.appendChild(scriptElement);
        head.removeChild(scriptElement);
    }
    return cleaned;
};


var scriptString = '<scrip' + 't + type="text/javascript">alert(\'test\');</scr' + 'ipt><strong>test</strong>';
document.getElementById('element').innerHTML = stripAndExecuteScript(scriptString);

vâng, phương pháp này hoạt động nhưng bạn sẽ gặp lỗi nếu bạn có nhận xét hoặc console.logs, vì vậy hãy coi chừng điều đó, bạn cũng có thể sửa đổi tài khoản cho các mô-đun var modules = [] var clean = text.replace (/ <script ([^>) ] *)> ([\ s \ S] *?) <\ / script> / gi, function (m, tags, script) {if (/type="module"/.test(tags)) {modules.push (script) return} scripts + = script + '\ n' return ''})
zavr

13
function insertHtml(id, html)  
{  
   var ele = document.getElementById(id);  
   ele.innerHTML = html;  
   var codes = ele.getElementsByTagName("script");   
   for(var i=0;i<codes.length;i++)  
   {  
       eval(codes[i].text);  
   }  
}  

Nó hoạt động trong Chrome trong dự án của tôi


Nhanh và đẹp. Cảm ơn bạn.
Jorge Fuentes González

Đó là nó! Cảm ơn bạn.
Floris

7

Một giải pháp mà không cần sử dụng "eval":

var setInnerHtml = function(elm, html) {
  elm.innerHTML = html;
  var scripts = elm.getElementsByTagName("script");
  // If we don't clone the results then "scripts"
  // will actually update live as we insert the new
  // tags, and we'll get caught in an endless loop
  var scriptsClone = [];
  for (var i = 0; i < scripts.length; i++) {
    scriptsClone.push(scripts[i]);
  }
  for (var i = 0; i < scriptsClone.length; i++) {
    var currentScript = scriptsClone[i];
    var s = document.createElement("script");
    // Copy all the attributes from the original script
    for (var j = 0; j < currentScript.attributes.length; j++) {
      var a = currentScript.attributes[j];
      s.setAttribute(a.name, a.value);
    }
    s.appendChild(document.createTextNode(currentScript.innerHTML));
    currentScript.parentNode.replaceChild(s, currentScript);
  }
}

Điều này về cơ bản sao chép thẻ script và sau đó thay thế thẻ script bị chặn bằng thẻ mới được tạo, do đó cho phép thực thi.


3

scriptNode.innerHTML = codekhông hoạt động cho IE. Điều duy nhất cần làm là thay thế bằng scriptNode.text = codevà nó hoạt động tốt


3

Sử dụng jquery $(parent).html(code)thay vì parent.innerHTML = code:

var oldDocumentWrite = document.write;
var oldDocumentWriteln = document.writeln;
try {
    document.write = function(code) {
        $(parent).append(code);
    }
    document.writeln = function(code) {
        document.write(code + "<br/>");
    }
    $(parent).html(html); 
} finally {
    $(window).load(function() {
        document.write = oldDocumentWrite
        document.writeln = oldDocumentWriteln
    })
}

Điều này cũng hoạt động với các tập lệnh sử dụng document.writevà các tập lệnh được tải qua srcthuộc tính. Thật không may, ngay cả điều này không hoạt động với các tập lệnh Google AdSense.


1
Điều gì khiến bạn nói rằng nó dễ dàng hơn? Nó thậm chí không ngắn hơn. Tôi luôn nghĩ rằng lạm dụng jQuery là một ý tưởng tồi.
Manngo

2

Cứ làm đi:

document.body.innerHTML = document.body.innerHTML + '<img src="../images/loaded.gif" alt="" onload="alert(\'test\');this.parentNode.removeChild(this);" />';

1
trông giống như một ý tưởng thiên tài
Pery Mimon

0

Bạn có thể xem qua bài đăng này . Mã có thể trông như thế này:

var actualDivToBeUpdated = document.getElementById('test');
var div = document.createElement('div');
div.innerHTML = '<script type="text/javascript">alert("test");<\/script>';
var children = div.childNodes;
actualDivToBeUpdated.innerHTML = '';
for(var i = 0; i < children.length; i++) {
    actualDivToBeUpdated.appendChild(children[i]);
}

0

Nhờ tập lệnh của Larry, hoạt động hoàn toàn tốt trong IE10, đây là những gì tôi đã sử dụng:

$('#' + id)[0].innerHTML = result;
$('#' + id + " script").each(function() { this.text = this.text || $(this).text();} );

0

Mở rộng của Larry's. Tôi đã thực hiện tìm kiếm đệ quy toàn bộ khối và các nút con.
Tập lệnh bây giờ cũng sẽ gọi các tập lệnh bên ngoài được chỉ định với tham số src. Các tập lệnh được nối vào phần đầu thay vì được chèn và được đặt theo thứ tự tìm thấy. Vì vậy, các kịch bản lệnh cụ thể được giữ nguyên. Và mỗi tập lệnh được thực thi đồng bộ tương tự như cách trình duyệt xử lý việc tải DOM ban đầu. Vì vậy, nếu bạn có một khối tập lệnh gọi jQuery từ CDN và hơn nút tập lệnh tiếp theo sử dụng jQuery ... Không có vấn đề gì! Ồ và tôi đã gắn thẻ các tập lệnh được nối thêm với một id được tuần tự hóa dựa trên những gì bạn đặt trong thông số thẻ để bạn có thể tìm thấy những gì đã được thêm bởi tập lệnh này.

exec_body_scripts: function(body_el, tag) {
    // Finds and executes scripts in a newly added element's body.
    // Needed since innerHTML does not run scripts.
    //
    // Argument body_el is an element in the dom.

    function nodeName(elem, name) {
        return elem.nodeName && elem.nodeName.toUpperCase() ===
              name.toUpperCase();
    };

    function evalScript(elem, id, callback) {
        var data = (elem.text || elem.textContent || elem.innerHTML || "" ),
            head = document.getElementsByTagName("head")[0] ||
                      document.documentElement;

        var script = document.createElement("script");
        script.type = "text/javascript";
        if (id != '') {
            script.setAttribute('id', id);
        }

        if (elem.src != '') {
            script.src = elem.src;
            head.appendChild(script);
            // Then bind the event to the callback function.
            // There are several events for cross browser compatibility.
            script.onreadystatechange = callback;
            script.onload = callback;
        } else {
            try {
                // doesn't work on ie...
                script.appendChild(document.createTextNode(data));      
            } catch(e) {
                // IE has funky script nodes
                script.text = data;
            }
            head.appendChild(script);
            callback();
        }
    };

    function walk_children(node) {
        var scripts = [],
          script,
          children_nodes = node.childNodes,
          child,
          i;

        if (children_nodes === undefined) return;

        for (i = 0; i<children_nodes.length; i++) {
            child = children_nodes[i];
            if (nodeName(child, "script" ) &&
                (!child.type || child.type.toLowerCase() === "text/javascript")) {
                scripts.push(child);
            } else {
                var new_scripts = walk_children(child);
                for(j=0; j<new_scripts.length; j++) {
                    scripts.push(new_scripts[j]);
                }
            }
        }

        return scripts;
    }

    var i = 0;
    function execute_script(i) {
        script = scripts[i];
        if (script.parentNode) {script.parentNode.removeChild(script);}
        evalScript(scripts[i], tag+"_"+i, function() {
            if (i < scripts.length-1) {
                execute_script(++i);
            }                
        });
    }

    // main section of function
    if (tag === undefined) tag = 'tmp';

    var scripts = walk_children(body_el);

    execute_script(i);
}

0

Hãy thử cái này, nó hoạt động với tôi trên Chrome, Safari và Firefox:

var script = document.createElement('script');
script.innerHTML = 'console.log("hi")';
document.body.appendChild(script); 
--> logs "hi"

Tuy nhiên, một điều cần lưu ý là tập lệnh sau div lồng nhau sẽ KHÔNG chạy:

var script = document.createElement('div');
script.innerHTML = '<script>console.log("hi")</script>';
document.body.appendChild(script);
--> doesn't log anything

Để một tập lệnh chạy, nó phải được tạo dưới dạng một nút sau đó được nối thêm dưới dạng con. Bạn thậm chí có thể thêm một tập lệnh vào bên trong một div đã được chèn trước đó và nó sẽ chạy (tôi đã gặp phải điều này trước đây khi cố gắng làm cho mã máy chủ quảng cáo hoạt động):

var div = document.createElement('div');
div.id = 'test-id';
document.body.appendChild(div);
var script = document.createElement('script');
script.innerHTML = 'console.log("hi")';
document.getElementById('test-id').appendChild(script);
--> logs "hi"

0

Chi câu trả lời của Lambder

document.body.innerHTML = '<img src="../images/loaded.gif" alt="" > onload="alert(\'test\');this.parentNode.removeChild(this);" />';

Bạn có thể sử dụng hình ảnh base64 để tạo và tải tập lệnh của mình

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMjHxIGmVAAAADUlEQVQYV2P4//8/AwAI/AL+iF8G4AAAAABJRU5ErkJggg=="
    onload="var script = document.createElement('script');  script.src = './yourCustomScript.js'; parentElement.append(script);" />

Hoặc nếu bạn có, Iframebạn có thể sử dụng nó thay thế

<iframe src='//your-orginal-page.com' style='width:100%;height:100%'
    onload="var script = document.createElement('script');  script.src = './your-coustom-script.js'; parentElement.append(script);"
    frameborder='0'></iframe>

0

Tôi cần thứ gì đó tương tự, nhưng cần tập lệnh được giữ nguyên hoặc được tạo lại ở cùng vị trí với tập lệnh gốc, vì tập lệnh của tôi nhắm mục tiêu vị trí của thẻ tập lệnh trong DOM để tạo / nhắm mục tiêu các phần tử. Tôi cũng làm cho tập lệnh đệ quy để đảm bảo rằng nó cũng hoạt động nếu nó bị giảm nhiều hơn một cấp.

LƯU Ý: Tôi sử dụng constở đây, nếu bạn có trình duyệt cũ hơn, chỉ cần sử dụng var.

    window.exec_body_scripts = function(body_el) {
        // ref: /programming/2592092/executing-script-elements-inserted-with-innerhtml based on Larry K's answer
        // Finds and executes scripts in a newly added element's body.
        // Needed since innerHTML does not run scripts.
        //
        // Argument body_el is an element in the dom.
        const
            type__Js = 'text/javascript',
            tagName__Script = 'script',
            tagName__Script__Upper = tagName__Script.toUpperCase();
        var scripts = [], script, i;
        function evalScript(elem) {
            var parent = elem.parentNode,
                data = (elem.text || elem.textContent || elem.innerHTML || ""),
                script = document.createElement(tagName__Script);

            script.type = type__Js;
            try {
                // doesn't work on ie...
                script.appendChild(document.createTextNode(data));
            } catch (e) {
                // IE has funky script nodes
                script.text = data;
            }
            // Make sure to re-insert the script at the same position
            // to make sure scripts that target their position
            // in the DOM function as expected.
            var parent = elem.parentNode;
            parent.insertBefore(script, elem);
            parent.removeChild(elem);
        };
        // Get all scripts (recursive)
        if (typeof (document.querySelectorAll) !== typeof (void 0)) {
            document.querySelectorAll('script').forEach((scr) => { if (!scr.type || scr.type.toLowerCase() === type__Js) scripts.push(scr); });
        }
        else {
            var children_nodes = body_el.childNodes, child;
            for (i = 0; children_nodes[i]; i++) {
                child = children_nodes[i];
                if (
                    child.nodeName
                    &&
                    child.nodeName.toUpperCase() === tagName__Script__Upper
                    &&
                    (
                        !child.type
                        ||
                        child.type.toLowerCase() === type__Js
                    )
                ) {
                    scripts.push(child);
                }
                // Recursive call
                window.exec_body_scripts(child);
            }
        }
        for (i = 0; scripts[i]; i++) {
            evalScript(scripts[i]);
        }
    };

0

Đã tạo chức năng trợ giúp mới này trong TypeScript, có thể ai đó sẽ đánh giá cao nó. Nếu bạn xóa khai báo kiểu khỏi tham số script, nó sẽ chỉ là JS thuần túy.

const evalPageScripts = () => {
  const scripts = document.querySelectorAll('script');

  scripts.forEach((script: HTMLScriptElement) => {
    const newScript = document.createElement('script');
    newScript.type = 'text/javascript';
    newScript.src = script.src;

    if (script.parentNode) {
      script.parentNode.removeChild(script);
    }

    return document.body.appendChild(newScript);
  })
};

export default evalPageScripts;


-1

Hãy thử hàm eval ().

data.newScript = '<script type="text/javascript">//my script...</script>'
var element = document.getElementById('elementToRefresh');
element.innerHTML = data.newScript;
eval(element.firstChild.innerHTML);

Đây là một ví dụ thực tế từ một dự án mà tôi đang phát triển. Cảm ơn bài viết này


-1

Đây là giải pháp của tôi trong một dự án gần đây.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Sample</title>
</head>
<body>
<h1 id="hello_world">Sample</h1>
<script type="text/javascript">
 var div = document.createElement("div");
  var t = document.createElement('template');
  t.innerHTML =  "Check Console tab for javascript output: Hello world!!!<br/><script type='text/javascript' >console.log('Hello world!!!');<\/script>";
  
  for (var i=0; i < t.content.childNodes.length; i++){
    var node = document.importNode(t.content.childNodes[i], true);
    div.appendChild(node);
  }
 document.body.appendChild(div);
</script>
 
</body>
</html>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.