Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
613 views
in Technique[技术] by (71.8m points)

javascript - Images created using `document.currentScript.ownerDocument.createElement` (from within <link> imported HTML) never load

Here's a function that returns the width of an image, given the image's url:

async function getImageWidthByUrl(imgUrl) {
  const imgEl = document.createElement("img");
  let untilImgLoaded = new Promise((resolve, reject) => {
    imgEl.onload = resolve;
    imgEl.onerror = reject;
  });
  imgEl.src = imgUrl;
  await untilImgLoaded;
  return imgEl.naturalWidth;
}

It works fine. It also (of course) works if we use new Image() instead of document.createElement("img").

However, the document.createElement("img") method doesn't work if document refers to the document object of a <link> html import.

Have a look at this example which imports this html. Notice that the console outputs:

"Starting..."
512
512

and never outputs the final 512 and then "Finished.", like it (seemingly) should. That's because the onload event of the imgEl never fires; the image never loads if it was created with document.currentScript.ownerDocument.createElement. I've tested this in Chrome 69.

Is this expected behaviour, or a bug? Shouldn't it at least throw an error if it's not possible to create an image using a <link>'s document?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's the normal behaviour.

The image referenced in the src attribute <img> element in an imported document with <link rel="import"> is not loaded until it is appended to the main document.

From the HTML Imports tutorial:

Think of content as inert until you call upon its services. [...]

Unless you append it's content to the DOM, it's a no-op. In fact, the only thing that "executes" in the import document directly is <script>.

You can apend it to the main document with document.apendNode().

Also, note that in your example, you should pass the imported document reference as an argument of the main function of simple-test.html for some reasons explained in this post or that post.

( function( ownerDocument ) {
    //...
    if( method === "document.currentScript.ownerDocument.createElement") {
        imgEl = ownerDocument.createElement("img")
        var imgOK = document.adoptNode( imgEl )
    }
    //...  
} ) ( document.currentScript.ownerDocument )

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...