允许JS在具有insertAdjacentHTML的AJAX .responseText中运行的工作方法(普通JS)

时间:2018-09-06 21:59:17

标签: javascript ajax

我阅读了文章,并从Google和Google尝试了许多方法,以获取如何使AJAX .responseText能够运行JS的方法,但这些方法都不起作用或产生故障,我需要一个有效的方法可以与insertAdjacentHTML正常使用。

代码

a.php

<style>
  #main {
    max-height: 800px;
    width: 400px;
    display: -webkit-flex; /* Safari */
    -webkit-flex-direction: column-reverse; /* Safari 6.1+ */
    display: flex;
    flex-direction: column-reverse;
    overflow: auto;
  }
</style>

<script>
  document.addEventListener('DOMContentLoaded', function(){ 

    document.querySelector('#executeAjax').addEventListener('click', sendAjax);

    function sendAjax(){
      var xhr= new XMLHttpRequest();
      xhr.onreadystatechange = function(){

        if(xhr.readyState === 4){
          document.querySelector('#ajax').insertAdjacentHTML('beforeend', xhr.responseText);
        }
      }

      xhr.open('POST','b.php'); 
      xhr.send();
    }

  });

</script>

<button id='executeAjax'>Execute</button>

<div id="main">
  <div id='ajax'></div>
</div>

b.php

<style>
iframe{
  display: block;
  width: 100px;
  height: 100px;
}
</style>

<script>
   alert('Hello');
</script>

<script>
   alert('Hello again');
</script>

<iframe src="https://www.youtube.com/embed/tgbNymZ7vqY"></iframe>

2 个答案:

答案 0 :(得分:0)

insertAdjacentHTML-ed后,如何手动评估脚本。

document.querySelectorAll('#ajax script').forEach(script => {
    script.remove()
    eval(script.innerHTML)
})

答案 1 :(得分:0)

如果我正确理解了该问题,以及您在注释(和其他问题)中提到的一些“问题”,则EASIEST解决方案是重构代码,以便B.PHP中的响应只是iframe src值(即无需HTML),只需创建一个iframe并设置源-

因为据我所知,每次样式/脚本标签都是相同的,所以您可以通过编程方式只为这些元素获取一次其他AJAX,但是我不会为此提供代码,因为那非常简单

相反,该解决方案对B.PHP中的输出进行了最小的更改

首先,为b.php响应中返回的“唯一”(即您只希望加载/运行一次的位)元素指定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>

现在,我之前建议的loadHTML代码:

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);
};

您将按如下所示更改XHR代码

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();
    }
});

现在,第一次调用loadHTML时,将添加所有元素-但是在第二次及以后的调用中,“已经”包含的具有特定ID的元素(上例中的样式和脚本)再次加载到DOM中