如何从 URL 数组向文档添加图像列表
How to add a list of images to the document from an array of URLs?
>假设我有一个充满图像源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>
一种方法是遍历图像数组,为每个图像创建一个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
- 我们将引入全局
i
和j
变量 - 我们没有使用 JavaScript 的精彩 Array 方法!
相反,让我们使用 documentFragment 和 JavaScript 的 forEach Array 方法。
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;
}
砰! 这是一个小提琴
既然提供了另一个赏金(我必须承认,我不完全同意另一个答案中的一些论点,但它确实使用了花哨的,甚至可以说有点"沉重"的现代方法(,我假设尼尔有一个更明显的答案,我将尝试一下。
想到的最直接的事情(假设 Q 没有对图像的标记/属性/等设置任何要求(是:Array.prototype.join([separator = ',']( 方法,它将数组的所有元素连接到一个字符串中,由作为 arguments[0]
(又名 separator
(传递的任何内容分隔,该字符串被强制为字符串(如果需要(或在省略时默认为字符串 ' ,
'(逗号(。
join
ing通常是一种非常流行的连接字符串的方式,因为它曾经在较旧和/或不太"流行"/"优化"的浏览器上更快。在后来更流行和优化更好的浏览器上,使用 +
的字符串连接目前似乎更快(这实际上是有道理的(。但是,在编写旨在向后兼容的代码时,选择/使用最慢的公分母通常是有意义的(因为速度怪物已经优化(。例如,请参阅SO上对这个和这个问题的答案(和链接的jsperfs(。
现在我们有一个字符串,我们将它与element.innerHTML
一起使用,这通常比访问 DOM 来createElement
图像并将其一遍又一遍地添加到documentFragment
的 DOM 中更快,然后再将这些元素移动到布局中的预期父元素......不要误会我的意思,当我们需要做大量的DOMwork而不在每个操作中重新绘制布局时,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>
这有一个小问题:如果我们的img
数组为空,我们会得到一个"空"图像。没有什么是一个简单的if
不能处理的。由于array.length
是基于 1 的,我们甚至可以让 JavaScript 强制 0
长度来false
。
此外,我们可以将其更改/膨胀为匿名(未命名(立即调用的函数表达式(IIFE(:
(function(container, arr){
if(arr.length) container.innerHTML = '<img src="' + arr.join('" /><img src="') + '" />';
}( document.getElementById('imageContainer')
, imgs
));
甚至接受围绕 url 的尾随和前导 HTML 代码的参数:
(function(container, arr, leadStr, trailStr){
if(arr.length) container.innerHTML = leadStr + arr.join(trailStr+leadStr) + trailStr;
}( document.getElementById('imageContainer')
, imgs
, '<img src="'
, '" />'
));
等等,等等等等...
根据实际(浏览器(引擎实现(和优化(,这个"加入"(像所有其他解决方案一样(很可能仍然在后台有一个循环。
由于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="'
, '" />'
));
所有这些都应该适用于任何使用HTML4和HTML5的浏览器。另请注意,上述内容将覆盖"容器"的内容(而不是添加到其中(。
然而,从技术上讲,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
));
请注意,此示例将添加到"容器"中的内容。
这些例子旨在概述几件事:innerHTML
,join
,没有必要引入全局/泄漏变量,最重要的是:没有什么可以"保存"一个"不必要的"循环(事实上,根据你正在做什么,可见循环实际上可能更快(。
但是,可以只命名包装函数(上面示例中的IIFE(并调用它们,传递所需的参数。这样,您可以多次动态添加或更新/覆盖图像区域(例如当您通过ajax等加载不同的图像url数组时(。
对于最后一个示例,我以"聪明"的方式使用了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>
希望这些例子之间的解释是尼尔所想到的。
无论如何,现在应该在这个答案和其他答案之间有足够的参考。
- 如何判断何时将dom节点添加到文档中
- 如何从 URL 数组向文档添加图像列表
- 将事件侦听器添加到文档,而不是签入元素存在,然后添加事件侦听器
- PouchDB,如何在已经有附件的文档中添加新附件
- JS触发器值检查在文档加载后添加到页面的元素在加载时更改AND
- 如何以编程方式将内容脚本添加到 iframe 文档
- 是否有 jQuery 事件用于何时将元素添加到文档中
- 使用单个HTML文档添加多个页面
- 在响应之前向文档添加其他字段
- 如何将 html 文档添加到另一个页面中的容器
- 如何使用严格:false模式的mongoose向mongoDB文档添加字段
- 向主干视图中的Cordova事件添加监听器,而不是向所有文档添加
- 传递信息到服务器端的功能在谷歌文档添加
- 在纯JavaScript中为文档添加onmousedown事件
- 在couchdb文档中使用javascript和html向现有文档添加字段的最简单方法
- 用文档添加脚本.Writeln不允许在开发人员工具中调试
- 在将mongodb文档添加到控制器中的数组中遇到麻烦
- 向现有MongoDB文档添加一个字段(在Node.js中使用Mongoose)
- 是否可以在CouchDB验证函数中向文档添加字段?
- 通过模态复选框选择将一个文档添加到另一个文档