2016-04-22 4 views
4

У меня есть следующая функция, и я пытаюсь найти лучший способ добавить несколько элементов, используя appendChild().Добавить несколько элементов в JavaScript

Когда пользователь нажимает кнопку Добавить, каждый элемент должен выглядеть следующим образом:

<li> 
    <input type="checkbox"> 
    <label>Content typed by the user</label> 
    <input type="text"> 
    <button class="edit">Edit</button> 
    <button class="delete">Delete</button> 
</li> 

и я эту функцию, чтобы добавить эти элементы:

function addNewItem(listElement, itemInput) { 
    var listItem = document.createElement("li"); 
    var listItemCheckbox = document.createElement("input"); 
    var listItemLabel = document.createElement("label"); 
    var editableInput = document.createElement("input"); 
    var editButton = document.createElement("button"); 
    var deleteButton = document.createElement("button"); 

    // define types 
    listItemCheckbox.type = "checkbox"; 
    editableInput.type = "text"; 

    // define content and class for buttons 
    editButton.innerText = "Edit"; 
    editButton.className = "edit"; 
    deleteButton.innerText = "Delete"; 
    deleteButton.className = "delete"; 

    listItemLabel.innerText = itemText.value; 

    // appendChild() - append these items to the li 
    listElement.appendChild(listItem); 
    listItem.appendChild(listItemCheckbox); 
    listItem.appendChild(listItemLabel); 
    listItem.appendChild(editButton); 
    listItem.appendChild(deleteButton); 

    if (itemText.value.length > 0) { 
    itemText.value = ""; 
    inputFocus(itemText); 
    } 
} 

Но вы можете заметить, что я повторяю три раза appendChild() за listItem. Можно ли добавить несколько элементов в appendChild()?

+0

Возможный дубликат Http: // StackOverflow .com/questions/9598916/speed-efficiency-of-multiple-dom-appendchild – Shakespeare

ответ

2

Лично я не понимаю, зачем вы это делаете.

Но если вам действительно нужно, чтобы заменить все appendChild() с помощью одного оператора, вы можете назначить outerHTML из созданных элементов к innerHTML из li элемента.

Вам просто нужно заменить следующее:

listElement.appendChild(listItem); 
    listItem.appendChild(listItemCheckbox); 
    listItem.appendChild(listItemLabel); 
    listItem.appendChild(editButton); 
    listItem.appendChild(deleteButton); 

С следующее:

listItem.innerHTML+= listItemCheckbox.outerHTML + listItemLabel.outerHTML + editButton.outerHTML + deleteButton.outerHTML; 
listElement.appendChild(listItem); 

Объяснение:

Атрибут интерфейса элемента DOM outerHTML получает сериализованный фрагмент HTML, описывающий элемент, включая его ndants. Поэтому назначение outerHTML созданных элементов в innerHTML элемента li аналогично добавлению к нему.

9

Вы можете сделать это с помощью DocumentFragment.

var documentFragment = document.createDocumentFragment(); 
documentFragment.appendChild(listItem); 
listItem.appendChild(listItemCheckbox); 
listItem.appendChild(listItemLabel); 
listItem.appendChild(editButton); 
listItem.appendChild(deleteButton); 
listElement.appendChild(documentFragment); 

DocumentFragments позволяет разработчикам размещать дочерние элементы на произвольном узел типа родительского , что позволяет узлы типа взаимодействий без истинного корневого узла. Это позволяет разработчикам создавать структуру , не делая этого внутри видимого DOM

+3

Но ни один из этих вызовов 'appendChild' не выполняется в живой DOM, поэтому браузер не будет пытаться повторно отобразить всю DOM после каждого ребенок добавляется. Вместо этого только один повторный рендеринг происходит после добавления всего фрагмента. –

+1

Отличный ответ - DocumentFragment - очень полезный способ внесения изменений в рендеринг DOM. –

+1

Это должен быть принятый ответ, поскольку он использует DOM API вместо строк. Очень крутой ответ. Спасибо. – 3Dos

3

Вам нужно добавить несколько детей? Просто сделайте его множественным с appendChildren!

Первые вещи сначала:

HTMLLIElement.prototype.appendChildren = function() { 

    for (var i = 0 ; i < arguments.length ; i++) 

    this.appendChild(arguments[ i ]); 

}; 

Тогда для любого элемента списка:

listElement.appendChildren(a, b, c, ...); 

//check : 
listElement.childNodes;//a, b, c, ... 

Работает с каждым элементом, который имеет appendChild метод, конечно! Мне нравится HTMLDivElement.

+0

Было бы неплохо совместить это с DocumentFragment в ответе Славика, чтобы сохранить несколько вызовов appendChild из основного DOM. –

+0

@AndFinally - искренне любопытно/не уверен: почему? Более дешевый оперативно для повторного добавления фрагмента, чем DOM? – RockinSocks

+2

@ RockinSocks Добавление серии узлов в фрагмент и добавление фрагмента только после того, как все собрано вместе, позволяет браузеру выполнять несколько перерасчетов по позиции и размеру элементов на странице, т. Е. Делать несколько переплавов. Таким образом, оплавление происходит только один раз, когда вы добавляете фрагмент в живой DOM. Таким образом, изменение должно получиться быстрее. См. Здесь краткое объяснение - https://www.sitepoint.com/10-ways-minimize-reflows-improve-performance/. –

3

Вы можете использовать метод append в JavaScript.

Это похоже на метод добавления jQuery, но он не поддерживает IE и Edge.

Вы можете изменить этот код

listElement.appendChild(listItem); 
listItem.appendChild(listItemCheckbox); 
listItem.appendChild(listItemLabel); 
listItem.appendChild(editButton); 
listItem.appendChild(deleteButton); 

в

listElement.append(listItem,listItemCheckbox,listItemLabel,editButton,deleteButton); 
1

Можно написать свою собственную функцию, если вы используете встроенный в arguments object

function appendMultipleNodes(){ 
    var args = [].slice.call(arguments); 
    for (var x = 1; x < args.length; x++){ 
     args[0].appendChild(args[x]) 
    } 
    return args[0] 
} 

Тогда вы назвали бы как таковой:

appendMultipleNodes(parent, nodeOne, nodeTwo, nodeThree) 
0

Объединение ответы от @Atrahasis и @Slavik:

Node.prototype.appendChildren = function() { 
    let children = [...arguments]; 

    if (
    children.length == 1 && 
    Object.prototype.toString.call(children[0]) === "[object Array]" 
) { 
    children = children[0]; 
    } 

    const documentFragment = document.createDocumentFragment(); 
    children.forEach(c => documentFragment.appendChild(c)); 
    this.appendChild(documentFragment); 
}; 

Это принимает детей как множественные аргументы, или в качестве единственного аргумента массива:

foo.appendChildren(bar1, bar2, bar3); 
bar.appendChildren([bar1, bar2, bar3]); 
+0

P.S. ES6 +, и я уверен, что это может быть написано лучше. Распространение узлов в массив/только прием массива для пути кода исключительных аргументов (в основном для использования 'forEach'), вероятно, довольно плохо. Кроме того, добавление функции в Node.prototype/подобный вариант, вероятно, вы не должны делать. – Pend

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