Working method to allow JS to run in AJAX .responseText with insertAdjacentHTML (Plain JS)

后端 未结 2 866
滥情空心
滥情空心 2021-01-28 18:46

I read and I tried many methods from posts and from Google on how to get the AJAX .responseText to allow JS to run and none of the methods either don\'t work or gav

相关标签:
2条回答
  • 2021-01-28 19:32

    If I understand the question correctly, and some of the "issues" you've mentioned in comments (and other questions), the EASIEST solution is to refactor your code so that the response in B.PHP is just the iframe src value (i.e. no need for HTML), and just create an iframe and set the source -

    since, as far as I can tell from comments, the style/script tags are the same each time, you can programatically just get some other AJAX for those elements once - but I'm not going to present code for that, as that is extremely simple

    Instead, a solution with minimal changes to what is output in B.PHP

    Firstly, give the "unique" (i.e. the bits you only want to load/run once) elements that are returned in the b.php response an ID

    <style id="onlyOnce1">
    iframe{
      display: block;
      width: 100px;
      height: 100px;
    }
    </style>
    
    <script id="onlyOnce2">
       alert('Hello');
    </script>
    
    <script id="onlyOnce3">
       alert('Hello again');
    </script>
    
    <iframe src="https://www.youtube.com/embed/tgbNymZ7vqY"></iframe>
    

    Now, the loadHTML code I suggested earlier:

    function loadHTML(text, dest, replace) {
        if (typeof dest == 'string') {
            dest = document.querySelector(dest);
        }
        var p = new DOMParser();
        var doc = p.parseFromString(text, 'text/html');
        var frag = document.createDocumentFragment();
        var id;
        while (doc.head.firstChild) {
            id = doc.head.firstChild.id;
            if(!(id && document.getElementById(id))) {
                // only add if id is not in DOM already
                frag.appendChild(doc.head.firstChild);
            }
        }
        while (doc.body.firstChild) {
            id = doc.head.firstChild.id;
            if(!(id && document.getElementById(id))) {
                // only add if id is not in DOM already
                frag.appendChild(doc.head.firstChild);
            }
        }
        [].forEach.call(frag.querySelectorAll('script'), function(script) {
            const scriptParent = script.parentNode || frag;
            const newScript = document.createElement('script');
            if (script.src) {
                newScript.src = script.src;
            } else {
                newScript.textContent = script.textContent;
            }
            scriptParent.replaceChild(newScript, script);
        });
        if (replace) {
            dest.innerHTML = '';
        }
        dest.appendChild(frag);
    };
    

    You'd change your XHR code as follows

    document.addEventListener('DOMContentLoaded', function() { 
        document.querySelector('#executeAjax').addEventListener('click', sendAjax);
        function sendAjax() {
            const xhr = new XMLHttpRequest();
            xhr.addEventListener('load', function() {
                loadHTML(xhr.responseText, '#ajax');
            });
            xhr.open('POST','b.php'); 
            xhr.send();
        }
    });
    

    Now, the FIRST time you loadHTML is called, all elements will be added - but on second and subsequent calls, the "already" included elements with a particular ID (style and script in the above example) will not be loaded into the DOM again

    0 讨论(0)
  • 2021-01-28 19:43

    After you have insertAdjacentHTML-ed, how about eval-ing the scripts manually.

    document.querySelectorAll('#ajax script').forEach(script => {
        script.remove()
        eval(script.innerHTML)
    })
    
    0 讨论(0)
提交回复
热议问题