2015-04-07 2 views
10

Предположим, у меня есть массив полный исходных изображений URL-адресов, например:Как добавить список изображений в документ из массива 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> 

ответ

26

Один из способов сделать это в цикле над массиве изображений, создать 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); 
} 

Однако это не особенно эффективен:

  • Мы используем ненужный цикл
  • Мы запрашивая РОМ на каждой итерации
  • Мы вводя глобальные переменные i и j
  • Мы не используем замечательные методы Array от 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

Хороший ответ! +1 Мне очень нравится реализация DocumentFragment. Я хотел бы указать, что 'Array.prototype.forEach()' недоступен в IE8. Просто что-то иметь в виду, если кто-то вынужден поддерживать этот архаичный браузер :-) –

+3

@HowardRenollet Хорошая точка. Иногда мне просто нравится притворяться, что IE8 и ниже не существуют. – monners

+0

Мне нравится притворяться, что IE не существует –

3

С другой щедростью предлагается (и я должен признать, что я не полностью согласен с некоторыми аргументами в другом ответе, который, однако, использует причудливые и даже, возможно, несколько «тяжелые» современные методы) Я предполагаю, что у Нила есть более очевидный ответ, я собираюсь сделать это.

Наиболее прямолинейная вещь, которая приходит на ум (учитывая, что Q не устанавливает никаких требований к разметке/атрибутам изображения/etc): Array.prototype. join ([separator = ',']) метод, который объединяет все элементы массива в строку, разделенную чем-либо, который передается как arguments[0] (aka separator), который принужден к строке (при необходимости) или по умолчанию string ',' (запятая) при опускании.
join IN часто был очень популярным способом конкатенации строк, потому что раньше он был быстрее на более старых и/или менее «популярных»/оптимизированных браузерах. В более поздних более популярных и оптимизированных браузерах строка-конкатенация с использованием + в настоящее время выглядит быстрее (что на самом деле имеет смысл).Однако при написании кода, который предназначен для обратной совместимости, часто имеет смысл выбирать/использовать наименее медленный общий знаменатель (поскольку скорости-монстры уже оптимизированы). См. Ответы (и связанные jsperfs) на this и this вопрос о SO, например.

Теперь, когда мы имеем строку, мы будем использовать его вместе с element.innerHTML, который often faster, чем доступ к DOM для createElement изображения и добавить его в DOM documentFragment «s снова и снова, прежде чем перейти эти элементы через к предполагаемый родительский элемент в макете ... Не поймите меня неправильно, documentFragment - это классная и полезная вещь, когда нам нужно сделать много DOMwork без получение макета-redraw в пути по каждому операция.

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

или даже принимать аргументы для завершающего и ведущий HTML код, окружающий URL,:

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

Etc, и т.д., и т.д ...

в зависимости от фактической реализации (браузера) двигателя (и оптимизаций), это «присоединиться» (как и все другие решения), скорее всего, до сих пор га петля са в фоновом режиме ..

Поскольку forEach обычно рассматривается как несколько медленный метод (мы все согласны, что еще петля на заднем плане), который, как правило, (как всегда, в зависимости от двигателя), чтобы сделать много больше работы, чем может потребоваться, и будет callBack функция (проходящая вокруг некоторых (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 и HT МЛ5. Также обратите внимание, что вышеперечисленное будет перезаписывать содержимое «container» (не добавлять к нему).

DOM-методы однако технически необходимы для X (H) ML, поскольку элементы официально не имеют свойства innerHTML (хотя многие браузеры не против), но мы все равно можем использовать простой (не- -hidden) петли, а не что-либо в глобальной области утечки, только путем модификации описанной выше функции:

(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 в приведенных выше примерах) и просто вызвать их, передав необходимые аргументы. Таким образом, вы можете добавлять или обновлять/перезаписывать свою область изображения динамически (например, когда вы загружаете разные файлы-url-массивы поверх ajax и т. Д.) Более одного раза.
Для этого последнего примера я использовал cloneNode в «умном» способе (который будет г-зип красиво) для того, чтобы свести к минимуму некоторых просмотров (в то время не оставляя нас с пережиток, но неразмещённым образом-узлом):

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>

Надеется объяснение между этими примерами является то, что имел в виде Нил ..
в любом случае, в настоящее время должен быть достаточно ссылок между этим и другим ответом (ов), чтобы пойти вокруг.

+0

hu .. где была сделана эта другая щедрость (предлагаемая @Neal), которая была открыта на 5 дней, когда я начал набирать этот ответ пару часов назад? Редактировать: не думаю, что я этого не понял, просто интересно о 5-дневном ... – GitaarLAB

+0

Хм, понял это. ([1] (http://meta.stackexchange.com/questions/107282/i-want -to-award-a-bounty-to-an-existing-answer-should-i-have-to-wait-24-hour), [2] (http://meta.stackexchange.com/questions/137939/ переопределять-на-награду существовавшей-ответ-баунти-причина)). По крайней мере, я не единственный, кто этого не понимал (.. «один или несколько ответов являются образцовыми и достойны дополнительной щедрости», это не означает, что «каждый может иметь возможность потенциально заработать щедрость) с большим ответом »). NP, я все еще придерживаюсь сути своего ответа. – GitaarLAB

Смежные вопросы