JavaScriptDOM i zdarzenia

Node.cloneNode()

Tworzy kopię węzła. Z argumentem true kopiuje też całą zawartość, czyli wszystkie elementy i teksty w środku.

Zwraca
Nowy węzeł, kopię oryginału, jeszcze niepodłączoną do dokumentu.
Na tej stronie

Przykład

#
JavaScript
const list = document.querySelector('#courses')
const original = list.querySelector('.course')

const deep = original.cloneNode(true)
const shallow = original.cloneNode()

deep.querySelector('strong').textContent = 'CSS'
list.append(deep)

console.log(list.children.length)
console.log(original.textContent)
console.log(deep.textContent)
console.log(shallow, shallow.childNodes.length)
Konsola
2
HTML 49 zł
CSS 49 zł
<li class="course"> 0

Definicja i zastosowanie

#

Metoda cloneNode() zwraca kopię elementu lub innego węzła. Kopia ma te same atrybuty, klasy i style inline, ale jest nowym, niezależnym obiektem: nie ma jej jeszcze w dokumencie, a zmiany w kopii nie wpływają na oryginał. Żeby ją pokazać, wstaw ją np. przez append().

Argument deep decyduje o zawartości. cloneNode(true) kopiuje element razem ze wszystkimi potomkami i tekstem. cloneNode() bez argumentu (albo z false) tworzy płytką kopię: sam element z atrybutami, ale pusty w środku. W praktyce prawie zawsze potrzebujesz true.

Kopia nie przejmuje obsługi zdarzeń dodanej przez addEventListener() ani własnych właściwości dopisanych do obiektu elementu w JavaScripcie. Kopiowane są za to atrybuty, w tym id, więc po wstawieniu kopii na stronie byłyby dwa elementy o tym samym identyfikatorze. Zmień go albo usuń przed wstawieniem.

Klonowanie często łączy się z elementem <template>: jego zawartość (template.content) kopiujesz przez cloneNode(true), uzupełniasz danymi i wstawiasz na stronę. To wygodny sposób na powtarzalne fragmenty, np. karty kursów.

Składnia

#
Składnia
node.cloneNode()
node.cloneNode(deep)

Parametry

#
  • deep

    opcjonalny, boolean

    true kopiuje węzeł razem z całą zawartością. Domyślnie false, czyli kopia bez dzieci.

Więcej przykładów

#
Obsługa zdarzeń nie jest kopiowana
JavaScript
const button = document.querySelector('#hint')
button.addEventListener('click', () => console.log('Podpowiedź z oryginału'))

const copy = button.cloneNode(true)
copy.id = 'hint-copy'
document.querySelector('#toolbar').append(copy)

copy.click()
button.click()
console.log(copy.id, copy.className)
Konsola
Podpowiedź z oryginału
hint-copy btn

Kliknięcie kopii nic nie wypisuje, bo cloneNode() przenosi atrybuty, ale nie obsługę dodaną przez addEventListener(). Kopia dostała też nowe id, żeby nie powielać identyfikatora.

Karty kursów z szablonu <template>
JavaScript
const template = document.querySelector('#card-template')
const cards = document.querySelector('#cards')
const courses = [
  { title: 'HTML', points: 120 },
  { title: 'CSS', points: 90 }
]

for (const course of courses) {
  const card = template.content.cloneNode(true)
  card.querySelector('h3').textContent = course.title
  card.querySelector('.points').textContent = `${course.points} pkt`
  cards.append(card)
}

console.log(cards.children.length)
console.log(cards.querySelector('.card:last-child h3').textContent)
Konsola
2
CSS

Zawartość <template> nie jest wyświetlana na stronie, służy tylko za wzór. Każde cloneNode(true) daje świeżą kopię, którą wypełniamy innymi danymi.

Obsługa przeglądarek

#

Szeroko dostępne

Działa we wszystkich nowoczesnych przeglądarkach, także na telefonach. Możesz używać bez obaw.

  • Chrome
  • Edge
  • Firefox
  • Safari

Dobre praktyki

#
  • Prawie zawsze wywołuj cloneNode(true). Bez argumentu dostaniesz pusty element, bez tekstu i dzieci.
  • Po sklonowaniu zmień lub usuń id, żeby na stronie nie było dwóch elementów o tym samym identyfikatorze.
  • Obsługę zdarzeń podepnij do kopii jeszcze raz albo obsługuj kliknięcia na wspólnym rodzicu (delegowanie zdarzeń).

Powiązane hasła

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.