javascript 如何从 URL 数组向文档添加图像列表?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29488371/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 10:37:14  来源:igfitidea点击:

How to add a list of images to the document from an array of URLs?

javascripthtml

提问by monners

Suppose I have an array full of image source URLs, like:

假设我有一个充满图像源 URL 的数组,例如:

var imgs = ['http://lorempizza.com/380/240', 
            'http://dummyimage.com/250/ffffff/000000', 
            'http://lorempixel.com/g/400/200/', 
            'http://lorempixel.com/g/400/200/sports/'];

How do I grab all of those images and insert them into my page at a particular location? Say...

如何获取所有这些图像并将它们插入到我页面的特定位置?说...

<div id="imageContainer"></div>

回答by monners

One way to do this is to loop over your array of images, create an imgelement for each, set the element's src to the current image source in your array, then append it to your container. This would look like:

一种方法是循环遍历图像数组,img为每个图像创建一个元素,将元素的 src 设置为数组中的当前图像源,然后将其附加到容器中。这看起来像:

var imgs = ['http://lorempizza.com/380/240', 
            'http://dummyimage.com/250/ffffff/000000', 
            'http://lorempixel.com/g/400/200/', 
            'http://lorempixel.com/g/400/200/sports/'];
var container = document.getElementById('imageContainer');

for (var i = 0, j = imgs.length; i < j; i++) {
    var img = document.createElement('img');
    img.src = imgs[i]; // img[i] refers to the current URL.
    container.appendChild(img);
}

However, this isn't particularly efficient:

但是,这并不是特别有效:

  • We're using an unnecessary loop
  • We're querying the dom on every iteration
  • We're introducing the global iand jvariables
  • We're not using JavaScript's wonderful Array methods!
  • 我们使用了一个不必要的循环
  • 我们在每次迭代中查询 dom
  • 我们正在引入全局ij变量
  • 我们没有使用 JavaScript 美妙的 Array 方法!

Instead, let's use a documentFragmentand JavaScript's forEachArray method.

相反,让我们使用documentFragment和 JavaScript 的forEachArray 方法。

var imgs = ['http://lorempizza.com/380/240', 
            'http://dummyimage.com/250/ffffff/000000', 
            'http://lorempixel.com/g/400/200/', 
            'http://lorempixel.com/g/400/200/sports/'];
var container = document.getElementById('imageContainer');
var docFrag = document.createDocumentFragment();

imgs.forEach(function(url, index, originalArray) {
    var img = document.createElement('img');
    img.src = url;
    docFrag.appendChild(img);
});


container.appendChild(docFrag);

This way we're:

这样我们:

  • Only hitting the DOM once
  • Not introducing global variables
  • Maintaining cleaner, easier to read code!
  • 只访问 DOM 一次
  • 不引入全局变量
  • 维护更干净,更易于阅读的代码!

Then just to make sure your new images look nice, add a bit of CSS to the mix:

然后只是为了确保您的新图像看起来不错,在混合中添加一些 CSS:

#imageContainer img {
    width: 20%;
    height: auto;
}

Bam! Here's a fiddle

砰!这是一把小提琴

回答by GitaarLAB

Since another bounty is offered (and I must admit that I don't fully agree with some of the arguments in the other answer, which does however use fancy and even arguably somewhat 'heavy' modern methods), I am assuming that Neal has a more obvious answer in mind, I'm going to have a shot at it.

由于提供了另一个赏金(我必须承认,我不完全同意另一个答案中的一些论点,但它确实使用了花哨的甚至可以说有些“沉重”的现代方法),我假设 Neal 有一个考虑到更明显的答案,我将尝试一下。

The most straight-forward thing that comes to mind (given that the Q doesn't set any requirements to the image's markup/attributes/etc) is: the Array.prototype.join([separator = ','])method which joins all elements of an array into a string, separated by anything that is passed as arguments[0](aka separator) which is coerced to string (if needed) ordefaults to the string ',' (comma) when omitted.
joining is/was often a very popular way to concatenate strings because it used to be faster on older and/or less 'popular'/'optimized' browsers. On the later more popular and better optimized browsers, string-concatenation using +currently appears to be faster (which actually makes sense). However, when writing code that is intended to be backwards compatible it often makes sense to choose/use the least slow common denominator (since the speed-monsters are already optimized). See answers (and linked jsperfs) to thisand thisquestion on SO for example.

想到的最直接的事情(假设 Q 没有对图像的标记/属性/等设置任何要求)是:Array.prototype。join([separator = ','])方法将数组的所有元素连接成一个字符串,由作为arguments[0](aka separator)传递的任何内容分隔,该字符串被强制转换为字符串(如果需要)默认为字符串 ' ,'(逗号) ) 省略时。
joining 通常是/曾经是一种非常流行的连接字符串的方式,因为它曾经在较旧和/或不太“流行”/“优化”的浏览器上更快。在后来更流行和更好优化的浏览器上,字符串连接使用+目前似乎更快(这实际上是有道理的)。然而,当编写旨在向后兼容的代码时,选择/使用最慢的公分母通常是有意义的(因为速度怪物已经被优化)。例如,在 SO 上查看这个这个问题的答案(和链接的 jsperfs)。

Now that we have a string, we'd use it together with element.innerHTMLwhich is often fasterthan accessing the DOM to createElementimage and add it to the documentFragment's DOM over and over again before moving these elements over to the intended parent element in the layout... Don't get me wrong, documentFragment is a cool and useful thing when we need to do a lot of DOMwork withoutgetting layout-redrawin the way on each and every operation.

现在,我们有一个字符串,我们可以使用它连同element.innerHTML往往更快比访问DOM来createElement的图像,并将其添加到documentFragment了布局移动这些元素所需的父元素之前的DOM一遍又一遍。 .. 不要误会我的意思,当我们需要做大量的 DOM 工作时,documentFragment 是一个很酷而且很有用的东西,不会在每次操作时都进行布局重绘

var imgs = ['http://lorempizza.com/380/240', 
            'http://dummyimage.com/250/ffffff/000000', 
            'http://lorempixel.com/g/400/200/', 
            'http://lorempixel.com/g/400/200/sports/'];

document.getElementById('imageContainer')
        .innerHTML = '<img src="' + imgs.join('" /><img src="') + '" />';
<div id="imageContainer"></div>

There is one tiny problem with this: we get one 'empty' image if our imgarray is empty. Nothing that a simple ifcan't handle tough.. Since array.lengthis 1-based we can even have javascript coerce a length of 0to false.
In addition we could change/bloat this to an anonymous (unnamed) immediately invoked function expression (IIFE):

这有一个小问题:如果我们的img数组是空的,我们就会得到一个“空”的图像。没有什么是简单的if不能处理困难的..由于array.length是基于 1 的,我们甚至可以让 javascript 强制转换为0to的长度false
此外,我们可以将其更改/膨胀为匿名(未命名)立即调用的函数表达式(IIFE):

(function(container, arr){
  if(arr.length) container.innerHTML = '<img src="' + arr.join('" /><img src="') + '" />';
}( document.getElementById('imageContainer')
 , imgs
));

or even accept arguments for the trailing and leading HTML code surrounding the url's:

甚至接受围绕 url 的尾随和前导 HTML 代码的参数:

(function(container, arr, leadStr, trailStr){
  if(arr.length) container.innerHTML = leadStr + arr.join(trailStr+leadStr) + trailStr;
}( document.getElementById('imageContainer')
 , imgs
 , '<img src="'
 , '" />'
));

Etc, etc, etc...

等等等等等等...

Depending on the actual (browser's) engine implementation (and optimizations), this 'join' (like all other solutions) most probably still has a loop in the background..

根据实际(浏览器的)引擎实现(和优化),这个“加入”(像所有其他解决方案一样)很可能在后台仍然有一个循环..

Since forEachis commonly seen as a somewhat slow method (we all agree there is still a loopin the background) which tends (as always, depending on engine) to do a lot more work than might be required and it will callBacka function (passing around some (3) arguments) for every element in the array, I'll present a loop-version here, using string-concatenation (for diversity in this answer and 'modern' 'faster' string-concatenation):

因为forEach通常被视为一种有点慢的方法(我们都同意在后台仍然有一个循环)它往往(一如既往,取决于引擎)做比可能需要的更多的工作,它会回调一个函数(传递围绕数组中的每个元素的一些(3)个参数),我将在这里展示一个循环版本,使用字符串连接(为了这个答案的多样性和“现代”“更快”字符串连接):

(function(container, arr, leadStr, trailStr){
  var i=0, L=arr.length, r='';
  if(L){
    for(; i<L ; ++i){
      r += leadStr + arr[i] + trailStr;
    }
  container.innerHTML = r;
  }
}( document.getElementById('imageContainer')
 , imgs
 , '<img src="'
 , '" />'
));

All of this should work on any browser using HTML4 and HTML5. Also note that the above will overwrite the contents of 'container' (not add to it).

所有这些都应该适用于任何使用 HTML4 和 HTML5 的浏览器。另请注意,上述内容将覆盖“容器”的内容(不添加)。

The DOM-methods however are technically required for X(H)ML as the elements don't have an innerHTMLproperty officially (although a lot of browsers don't mind), but we can still use a simple (non-hidden) loop while not leaking anything to the global scope, just by modifying the above function:

然而,DOM 方法在技术上是 X(H)ML 所必需的,因为元素没有innerHTML正式的属性(尽管很多浏览器不介意),但我们仍然可以使用一个简单的(非隐藏)循环,而不会向全局范围泄漏任何内容,只需修改上述函数即可:

(function(container, arr){
  var i = 0, L = arr.length, docFrag = document.createDocumentFragment();
  if(L){
    for(; i<L; ++i){
      docFrag.appendChild(document.createElement('img')).src = arr[i];
    }
    container.appendChild(docFrag);
  }
}( document.getElementById('imageContainer')
 , imgs
));

Note that this example addsto the content in 'container'.

请注意,此示例添加到“容器”中的内容。

These examples are intended to outline a couple of things: innerHTML, join, there is no need to introduce global/leaking variables and most importantly: nothing 'saves' an 'unnecessary' loop (in fact, depending on what you are doing, the visible loop might actually be faster).

这些示例旨在概述一些事情:innerHTML, join,无需引入全局/泄漏变量,最重要的是:没有什么可以“保存”“不必要的”循环(实际上,取决于您在做什么,可见循环实际上可能更快)。

However, one might just name the wrapping functions (IIFE in above examples) and just call them, passing your required arguments. That way you can add to or update/overwrite your image-area dynamically (like when you'd load different image-url-array's over ajax etc..) more than once.
For this final example I've used cloneNodein a 'clever' way (that will g-zip nicely) in order to minimize some lookups (whilst not leaving us with a leftover, but unplaced image-node):

然而,人们可能只是命名包装函数(上面示例中的 IIFE)并调用它们,传递您所需的参数。这样你就可以动态地添加或更新/覆盖你的图像区域(比如当你通过 ajax 加载不同的图像 url-array 时等等)不止一次。
对于这最后一个示例,我cloneNode以一种“聪明”的方式使用(这将很好地进行 g-zip)以最小化一些查找(同时不会给我们留下剩余但未放置的图像节点):

var imgs = ['http://lorempizza.com/380/240', 
            'http://dummyimage.com/250/ffffff/000000', 
            'http://lorempixel.com/g/400/200/', 
            'http://lorempixel.com/g/400/200/sports/'];

function addPics(container, arr){
  var i = 0, L = arr.length, docFrag = document.createDocumentFragment(), img;
  if(L){
    for( docFrag.appendChild(img=document.createElement('img')).src = arr[i]
       ; ++i<L
       ; docFrag.appendChild(img.cloneNode(false)).src = arr[i]
       );
    container.appendChild(docFrag);
  }
}

addPics( document.getElementById('imageContainer'), imgs );
<div id="imageContainer"></div>

Hopefully the explanations between these examples are what Neal had in mind..
In any case, there should now be enough reference between this and other answer(s) to go around.

希望这些例子之间的解释是尼尔想到的。
无论如何,现在应该有足够的参考来解决这个问题和其他答案。