最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How do i use the fetch api to load html page with its javascript? - Stack Overflow

programmeradmin5浏览0评论

I'm trying to load HTML page with its JavaScript scripts using the fetch API

I could use ajax and JQuery See here to load the page but, is it possible with fetch API?

Here is a code demonstration:

Am assuming your running this on localhost

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>fetch API</title>
</head>
<body>
    <p>index page</p>
    <div id="content">

    </div>

<script>
    fetch('./page.html')
        .then(data => data.text())
        .then(html => document.getElementById('content').innerHTML = html);
</script>
</body>
</html>

the page to be loaded:

<!-- page.html -->
<p> i am the loaded page</p>
<script type="text/javascript">
    alert("Javascript is working");
</script>

The <p> tag I am the loaded page will run but the <script> wont alert or any kind of JavaScript

I'm trying to load HTML page with its JavaScript scripts using the fetch API

I could use ajax and JQuery See here to load the page but, is it possible with fetch API?

Here is a code demonstration:

Am assuming your running this on localhost

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>fetch API</title>
</head>
<body>
    <p>index page</p>
    <div id="content">

    </div>

<script>
    fetch('./page.html')
        .then(data => data.text())
        .then(html => document.getElementById('content').innerHTML = html);
</script>
</body>
</html>

the page to be loaded:

<!-- page.html -->
<p> i am the loaded page</p>
<script type="text/javascript">
    alert("Javascript is working");
</script>

The <p> tag I am the loaded page will run but the <script> wont alert or any kind of JavaScript

Share Improve this question edited Sep 18, 2019 at 7:48 Ahmad Karimi 1,3733 gold badges15 silver badges27 bronze badges asked Sep 18, 2019 at 7:44 xaander1xaander1 1,1602 gold badges16 silver badges41 bronze badges
Add a comment  | 

5 Answers 5

Reset to default 7

Please refer stackoverflow for inserting script into innerhtml .

I have done the changes in index.html and its working for me. Please find the code below

  fetch('./page.html')
.then(function (data) {
  return data.text();
})
.then(function (html) {
  document.getElementById('content').innerHTML = html;
  var scripts = document.getElementById("content").querySelectorAll("script");
  for (var i = 0; i < scripts.length; i++) {
    if (scripts[i].innerText) {
      eval(scripts[i].innerText);
    } else {
      fetch(scripts[i].src).then(function (data) {
        data.text().then(function (r) {
          eval(r);
        })
      });

    }
    // To not repeat the element
    scripts[i].parentNode.removeChild(scripts[i]);
  }
});

I found the other answer using eval() here helpful, but ran into a problem as my dynamically loaded content was importing an external script giving CORS warnings in Firefox, for example:

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>

I therefore tweaked it a little to inject script tags without using eval() to allow external scripts from other domains as well as embedded scripts. I then modified to load the scripts in the order they are defined, waiting for the load to complete before loading the next - this was due to the fact that an embedded script on my page depended on functionality from the external scripts being loaded.

fetch("/mypage.html").then(response => {
    return response.text();
}).then(data => {

    const app = document.getElementById("app");
    app.innerHTML = data;

    // Load scripts in the order they are defined
    // Note that inserting scripts into an element using innerHTML doesnt work - hence this logic
    var scripts = app.querySelectorAll("script");

    if (scripts !== null && scripts.length > 0) {
        var loadScript = index => {
            if (index < scripts.length) {
                var newScript = document.createElement("script");

                if (scripts[index].innerText) {
                    var inlineScript = document.createTextNode(scripts[index].innerText);
                    newScript.appendChild(inlineScript);
                }
                else {
                    newScript.src = scripts[index].src;
                }
                scripts[index].parentNode.removeChild(scripts[index]);
                newScript.addEventListener("load", event => loadScript(index + 1));
                newScript.addEventListener("error", event => loadScript(index + 1));
                app.appendChild(newScript);
            }
        }

        loadScript(0); // Start loading script 0. Function is recursive to load the next script after the current one has finished downloading.
    }
}).catch(err => {
    console.warn('Something went wrong.', err);
});  

I released this tiny Fetch data loader on Github, which does exactly what you're asking for.

The loadData() function loads the fetched content into a target container then run its scripts. It also accepts callbacks.

A demo is available here: https://www.ajax-fetch-data-loader.miglisoft.com

Here's a sample code:

<script>
document.addEventListener('DOMContentLoaded', function(event) {
    fetch('ajax-content.php')
    .then(function (response) {
        return response.text()
    })
    .then(function (html) {
        console.info('content has been fetched from data.html');
        loadData(html, '#ajax-target').then(function (html) {
            console.info('I\'m a callback');
        })
    }).catch((error) => {
        console.log(error);
    });
});
</script>

based on phil_rawlings's answer I ended up using this piece of code

let scripts = app.querySelectorAll("script");

scripts.forEach((script) => {
    let newScript = document.createElement("script");

    newScript.src = script.src;

    script.parentNode.removeChild(script);

    newScript.addEventListener("load", event => script);
    newScript.addEventListener("error", event => script);

    app.appendChild(newScript);
});

You can use the hmpl-js package to load HTML from the server. It works on fetch, so it can help you avoid writing a bunch of code:

<div id="wrapper"></div>
<script src="https://unpkg.com/hmpl-js"></script>
<script>
const templateFn = hmpl.compile(
    `<div>
       { 
         {
           "src":"http://localhost:8000/api/test" 
         } 
       }
    </div>`
  );

  const wrapper = document.getElementById("wrapper");

  const obj = templateFn();

  wrapper.appendChild(obj.response);
</script>

or

import { compile } from "hmpl-js";

const templateFn = hmpl.compile(
  `<div>
     { 
       {
         "src":"http://localhost:8000/api/test" 
       } 
     }
  </div>`
);

const wrapper = document.getElementById("wrapper");

const obj = templateFn();

wrapper.appendChild(obj.response);
发布评论

评论列表(0)

  1. 暂无评论