如何从一组URL中添加图像列表到文档?

时间:2015-04-07 09:34:47

标签: javascript html

假设我有一个包含图像源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/'];

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

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

2 个答案:

答案 0 :(得分:27)

执行此操作的一种方法是遍历图像数组,为每个图像创建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);
}

然而,这并不是特别有效:

  • 我们正在使用不必要的循环
  • 我们在每次迭代时查询dom
  • 我们正在引入全球ij变量
  • 我们没有使用JavaScript精彩的数组方法!

相反,我们使用documentFragment和JavaScript的forEach数组方法。

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

这样我们就可以了:

  • 只打一次DOM
  • 不引入全局变量
  • 保持更清晰,更易于阅读的代码!

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

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

的Bam!这是fiddle

答案 1 :(得分:4)

由于提供了另一个赏金(我必须承认我并不完全同意另一个答案中的一些论点,但是它确实使用了花哨的,甚至可以说有点'重'的现代方法),我假设Neal心中有一个更明显的答案,我准备好了。

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

现在我们有了一个字符串,我们将element.innerHTMLcreateElement一起使用,而不是将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>在将这些元素移动到布局中的预期父元素之前,一遍又一遍地使用DOM ... 不要误解我的意思,当我们需要做很多DOMwork 在每个中获取布局 - 重绘时,documentFragment是一个很酷且有用的东西和每一次行动。

img
if

这有一个小问题:如果我们的array.length数组为空,我们会得到一个'空'图像。简单的0无法处理艰难的事情。由于false是基于1的,我们甚至可以将javascript强制为(function(container, arr){ if(arr.length) container.innerHTML = '<img src="' + arr.join('" /><img src="') + '" />'; }( document.getElementById('imageContainer') , imgs )); (function(container, arr, leadStr, trailStr){ if(arr.length) container.innerHTML = leadStr + arr.join(trailStr+leadStr) + trailStr; }( document.getElementById('imageContainer') , imgs , '<img src="' , '" />' )); 的长度。
此外,我们可以将此变为/膨胀为匿名(未命名)立即调用的函数表达式(often faster):

forEach

甚至接受有关网址的尾随和前导HTML代码的参数:

(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="'
 , '" />'
));
<等等等等......

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

由于innerHTML通常被认为是一种有点慢的方法(我们都同意在后台仍然是一个循环),它倾向于(一如既往,取决于引擎)比可能需要更多的工作,它将 callBack 一个函数(传递一些(3)参数)为数组中的每个元素,我将在这里提出一个循环版本,使用字符串连接(对于这个答案中的多样性和'现代''更快'字符串连接):

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

所有这些都适用于任何使用HTML4和HTML5的浏览器。另请注意,上面将覆盖'container'的内容(不添加到它)。

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

join

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

这些示例旨在概述以下几点:cloneNodevar 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 );,不需要引入全局/泄漏变量,最重要的是:没有“保存”“不必要”的循环(事实上,根据你正在做的事情,可见循环可能实际上更快)。

但是,人们可能只是命名包装函数(上例中的IIFE)并只调用它们,传递所需的参数。这样你就可以动态地添加或更新/覆盖你的图像区域(就像你在ajax等上加载不同的image-url-array一样)。不止一次。
对于这个最后的例子,我以'聪明'的方式使用<div id="imageContainer"></div>(这将很好地g-zip),以便最大限度地减少一些查找(同时不会让我们留下剩余的,但未放置的图像节点): / p>

{{1}}
{{1}}

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