Zazwyczaj programiści używają jQuery, gdy muszą coś zrobić z DOM. Jednak prawie każdą manipulację DOM można wykonać na czysty JavaScript za pomocą interfejsu API DOM.

Przyjrzyjmy się temu API bardziej szczegółowo:

Na koniec napiszesz własną prostą bibliotekę DOM, którą będzie można wykorzystać w dowolnym projekcie.

Zapytania DOM

Zapytania DOM są wykonywane przy użyciu metody .querySelector(), która jako argument przyjmuje dowolny selektor CSS.

Const myElement = document.querySelector("#foo > div.bar")

Zwróci pierwszy pasujący element. Możesz zrobić odwrotnie - sprawdź, czy element pasuje do selektora:

MójElement.matches("div.bar") === true

Jeśli chcesz pobrać wszystkie elementy pasujące do selektora, użyj następującej konstrukcji:

Const myElements = document.querySelectorAll(.bar")

Jeśli wiesz, do którego elementu rodzica się odnosić, możesz po prostu przeszukać jego elementy potomne, zamiast przeszukiwać cały kod:

Const myChildElemet = myElement.querySelector("input") // Zamiast: // document.querySelector("#foo > div.bar input")

Powstaje pytanie: po co więc używać innych, mniej wygodnych metod, takich jak.getElementsByTagName() ? Jest mały problem - wynik działania output.querySelector() nie jest aktualizowany, a gdy dodamy nowy element(patrz ), to się nie zmieni.

const elements1 = document.querySelectorAll("div") const elements2 = document.getElementsByTagName("div") const newElement = document.createElement("div") document.body.appendChild(newElement) elements1.length === elements2.length // fałszywy

Również querySelectorAll() zbiera wszystko w jedną listę, co czyni ją niezbyt wydajną.

Jak pracować z listami?

Co więcej, .querySelectorAll() ma dwa małe dziwactwa. Nie możesz po prostu wywoływać metod na wynikach i oczekiwać, że zostaną zastosowane do każdego z nich (jak możesz być przyzwyczajony do robienia z jQuery). W każdym razie będziesz musiał wykonać iterację po wszystkich elementach pętli. Po drugie, zwracany obiekt jest listą elementów, a nie tablicą. Dlatego metody tablicowe nie będą działać. Oczywiście istnieją metody dla list, takie jak .forEach() , ale niestety nie są one odpowiednie dla wszystkich przypadków. Lepiej więc przekonwertować listę na tablicę:

// Używanie Array.from() Array.from(myElements).forEach(doSomethingWithEachElement) // Lub prototyp tablicy (przed ES6) Array.prototype.forEach.call(myElements, doSomethingWithEachElement) // Łatwiej: .forEach.call (mojeElementy , zróbCośZKażdymElementem)

Każdy element ma pewne właściwości, które odnoszą się do „rodziny”.

MójElement.dzieci mójElement.firstElementMoje dzieckoElement.lastElementMojElement.dziecko.previousElementRodzeństwo mójElement.nextElementRodzeństwo

Ponieważ interfejs Element jest dziedziczony z interfejsu węzła, obecne są również następujące właściwości:

MyElement.childNodes myElement.firstChild myElement.lastChild myElement.previousSibling myElement.nextSibling myElement.parentNode myElement.parentElement

Pierwsze właściwości odnoszą się do elementu, a drugie (z wyjątkiem .parentElement) mogą być listami elementów dowolnego typu. W związku z tym możesz sprawdzić typ elementu:

MyElement.firstChild.nodeType === 3 // ten element będzie węzłem tekstowym

Dodawanie klas i atrybutów

Dodanie nowej klasy jest bardzo proste:

myElement.classList.add("foo") myElement.classList.remove("bar") myElement.classList.toggle("baz")

Dodanie właściwości do elementu jest dokładnie takie samo, jak dodanie właściwości do dowolnego obiektu:

// Pobierz wartość atrybutu const value = myElement.value // Ustaw atrybut jako właściwość elementu myElement.value = "(!LANG:foo" // Для установки нескольких свойств используйте.Object.assign() Object.assign(myElement, { value: "foo", id: "bar" }) // Удаление атрибута myElement.value = null !}

Możesz użyć metod .getAttibute() , .setAttribute() i .removeAttribute() . Natychmiast zmienią atrybuty HTML elementu (w przeciwieństwie do właściwości DOM), co spowoduje ponowne narysowanie przeglądarki (będziesz mógł zobaczyć wszelkie zmiany, sprawdzając element za pomocą narzędzi programistycznych w przeglądarce). Takie przerysowania nie tylko wymagają więcej zasobów niż ustawianie właściwości DOM, ale mogą również prowadzić do nieoczekiwanych błędów.

Są one zwykle używane w elementach, które nie mają odpowiednich właściwości DOM, takich jak colspan . Lub jeśli ich użycie jest naprawdę konieczne, na przykład dla właściwości HTML podczas dziedziczenia (patrz).

Dodawanie stylów CSS

Dodaje się je w taki sam sposób, jak inne właściwości:

MyElement.style.marginLeft = "2em"

Niektóre niektóre właściwości można ustawić za pomocą .style , ale jeśli chcesz uzyskać wartości po pewnych obliczeniach, lepiej użyć window.getComputedStyle() . Ta metoda pobiera element i zwraca CSSStyleDeclaration zawierającą style zarówno samego elementu, jak i jego rodzica:

Window.getComputedStyle(myElement).getPropertyValue("pozostały margines")

Zmiana DOM

Możesz przenosić elementy:

// Dodanie elementu 1 jako ostatniego dziecka elementu 2 element1.appendChild(element2) // Wstawienie elementu 2 jako dziecka elementu 1 przed elementem 3 element1.insertBefore(element2, element3)

Jeśli nie chcesz się przenosić, ale chcesz wkleić kopię, użyj:

// Utwórz klon const myElementClone = myElement.cloneNode() myParentElement.appendChild(myElementClone)

Metoda .cloneNode() przyjmuje jako argument wartość logiczną, a jeśli true , klonuje i elementy potomne.

Oczywiście możesz tworzyć nowe elementy:

const myNewElement = document.createElement("div") const myNewTextNode = document.createTextNode("jakiś tekst")

A następnie wstaw je, jak pokazano powyżej. Nie możesz usunąć elementu bezpośrednio, ale możesz to zrobić poprzez element nadrzędny:

MyParentElement.removeChild(myElement)

Możesz również odwołać się pośrednio:

MyElement.parentNode.removeChild(myElement)

Metody na elementach

Każdy element ma właściwości takie jak .innerHTML i .textContent , zawierają kod HTML i odpowiednio sam tekst. Poniższy przykład zmienia zawartość elementu:

// Zmień kod HTML myElement.innerHTML = `

Nowa treść

bip bup bip bup

` // Spowoduje to usunięcie treści myElement.innerHTML = null // Dodaje do HTML myElement.innerHTML += ` kontynuuj czytanie...

W rzeczywistości zmiana kodu HTML jest złym pomysłem, ponieważ powoduje utratę wszystkich zmian, które zostały wprowadzone wcześniej, a także przeciąża obsługę zdarzeń. Lepiej jest używać tej metody tylko poprzez całkowite odrzucenie całego kodu HTML i zastąpienie go kopią z serwera. Lubię to:

const link = document.createElement("a") const text = document.createTextNode("kontynuuj czytanie...") const hr = document.createElement("hr") link.href = "foo.html" link.appendChild( tekst) myElement.appendChild(link) myElement.appendChild(hr)

Spowoduje to jednak dwa przerysowania przeglądarki, podczas gdy .innerHTML spowoduje tylko jedno. Możesz obejść ten problem, jeśli najpierw dodasz wszystko do DocumentFragment , a następnie dodasz potrzebny fragment:

Const fragment = document.createDocumentFragment() fragment.appendChild(tekst) fragment.appendChild(hr) myElement.appendChild(fragment)

Obsługa zdarzeń

Jeden z najprostszych handlerów:

MyElement.onclick = funkcja onclick (zdarzenie) ( console.log(event.type + " został zwolniony") )

Ale co do zasady należy tego unikać. Tutaj .onclick jest właściwością elementu i teoretycznie możesz ją zmienić, ale nie będziesz w stanie dodać innych funkcji obsługi za pomocą kolejnej funkcji, która odwołuje się do starej.

Lepiej jest użyć .addEventListener(), aby dodać moduły obsługi. Przyjmuje trzy argumenty: typ zdarzenia, funkcję, która będzie wywoływana przy każdym uruchomieniu, oraz obiekt konfiguracyjny (do tego dojdziemy później).

MyElement.addEventListener("klik", funkcja (zdarzenie) ( console.log(zdarzenie.type + " zostało uruchomione") )) myElement.addEventListener("klik", funkcja (zdarzenie) ( console.log(event.type + " został zwolniony") ))

Właściwość event.target odwołuje się do elementu, do którego jest dołączone zdarzenie.

Dzięki temu możesz uzyskać dostęp do wszystkich właściwości:

// Właściwość `forms` jest tablicą zawierającą łącza do wszystkich formularzy const myForm = document.forms const myInputElements = myForm.querySelectorAll("input") Array.from(myInputElements).forEach(el => ( el.addEventListener(") zmiana", funkcja (zdarzenie) ( console.log(event.target.value) )) ))

Zapobieganie domyślnym działaniom

W tym celu używana jest metoda .preventDefault(), która blokuje standardowe akcje. Na przykład zablokuje przesłanie formularza, jeśli autoryzacja po stronie klienta nie powiodła się:

MyForm.addEventListener("submit", function (event) ( const name = this.querySelector("#name") if (name.value === "(!LANG:Donald Duck") { alert("You gotta be kidding!") event.preventDefault() } }) !}

Metoda .stopPropagation() pomoże, jeśli masz określoną procedurę obsługi zdarzeń dołączoną do elementu podrzędnego i drugą procedurę obsługi tego samego zdarzenia dołączoną do elementu nadrzędnego.

Jak wspomniano wcześniej, metoda .addEventListener() przyjmuje opcjonalny trzeci argument jako obiekt konfiguracyjny. Ten obiekt musi zawierać jedną z następujących właściwości logicznych (wszystkie domyślnie ustawione na false):

  • przechwytywanie: zdarzenie zostanie dołączone do tego elementu przed jakimkolwiek innym elementem poniżej w DOM;
  • raz: wydarzenie można przypiąć tylko raz.
  • pasywny: event.preventDefault() zostanie zignorowany (wyjątek podczas błędu).

Najpopularniejszą właściwością jest .capture , która jest tak powszechna, że ​​można ją zastosować w skrócie: zamiast przekazywać ją w obiekcie konfiguracyjnym, po prostu podaj jej wartość tutaj:

MyElement.addEventListener(typ, listener, true)

Programy obsługi są usuwane za pomocą metody .removeEventListener(), która przyjmuje dwa argumenty: typ zdarzenia i odwołanie do procedury obsługi do usunięcia. Na przykład właściwość Once można zaimplementować w następujący sposób:

MyElement.addEventListener("zmiana", funkcja listener (zdarzenie) ( console.log(event.type + " został wyzwolony na " + this) this.removeEventListener("change", listener) ))

Dziedzictwo

Załóżmy, że masz element i chcesz dodać obsługę zdarzeń dla wszystkich jego elementów podrzędnych. Następnie musiałbyś przejść przez nie za pomocą metody myForm.querySelectorAll("input"), jak pokazano powyżej. Możesz jednak po prostu dodać elementy do formularza i sprawdzić ich zawartość za pomocą event.target .

MyForm.addEventListener("change", function (event) ( const target = event.target if (target.matches("input")) ( console.log(target.value) ) ))

I jeszcze jednym plusem tej metody jest to, że handler będzie automatycznie dołączany do nowych elementów potomnych.

Animacja

Najłatwiejszym sposobem dodania animacji jest użycie CSS z właściwością przejścia. Ale dla większej elastyczności (na przykład w przypadku gry) lepiej nadaje się JavaScript.

Wywoływanie metody window.setTimeout() do momentu zakończenia animacji nie jest dobrym pomysłem, ponieważ aplikacja może się zawiesić, zwłaszcza na urządzeniach mobilnych. Lepiej jest użyć window.requestAnimationFrame(), aby zapisać wszystkie zmiany do następnego przerysowania. Jako argument przyjmuje funkcję, która z kolei otrzymuje znacznik czasu:

const start = window.performance.now() const duration = 2000 window.requestAnimationFrame(funkcja fadeIn (now)) ( const progress = now - start myElement.style.opacity = postęp / czas trwania if (progress< duration) { window.requestAnimationFrame(fadeIn) } }

W ten sposób uzyskuje się bardzo płynną animację. W swoim artykule Mark Brown omawia ten temat.

Pisanie własnej biblioteki

Fakt, że w DOM musisz cały czas iterować po elementach, aby coś z nimi zrobić, może wydawać się dość nudny w porównaniu do składni jQuery $(".foo").css((color: "red")). Ale dlaczego nie napisać kilku własnych metod, które ułatwią to zadanie?

Const $ = funkcja $(selector, context = document) ( const elements = Array.from(context.querySelectorAll(selector)) return ( elementy, html (newHtml) ( this.elements.forEach(element => ( element.innerHTML = newHtml )) zwróć to ), css (newCss) ( this.elements.forEach(element => ( Object.assign(element.style, newCss) )) zwróć to ), on (zdarzenie, handler, opcje) ( this.elements .forEach(element => ( element.addEventListener(zdarzenie, handler, opcje) )) zwróć to ) ) )

Pseudo kod

$(".rightArrow").click(function() ( rightArrowParents = this.dom(); //.dom(); jest pseudofunkcją ... powinna pokazać cały alert(rightArrowParents); ));

Komunikat alarmowy będzie następujący:

body div.lol a.rightArrow

Jak mogę to uzyskać za pomocą javascript/jquery?

Używanie jQuery w ten sposób (po którym następuje rozwiązanie, które nie używa jQuery z wyjątkiem zdarzenia, znacznie mniej wywołań funkcji, jeśli to ma znaczenie):

Przykład w czasie rzeczywistym:

$(".rightArrow").click(function() ( var rightArrowParents = ; $(this).parents().addBack().not("html").each(function() ( var wpis = this.tagName .toLowerCase(); if (this.className) ( wpis += "." + this.className.replace(/ /g, "."); ) rightArrowParents.push(entry; )); alert(rightArrowParents.join (" "); zwróć fałszywe; ));

Kliknij tutaj

(W przykładach na żywo zaktualizowałem atrybut class w div do lol multi, aby zademonstrować obsługę wielu klas.)

Oto rozwiązanie dla dokładnego dopasowania elementów.

Ważne jest, aby zrozumieć, że selektor (nie jest prawdziwe), które pokazują narzędzia chrome, nie identyfikują jednoznacznie elementu w DOM. ( , na przykład, nie rozróżnia listy kolejnych elementów span. Brak informacji o pozycjonowaniu/indeksowaniu)

$.fn.fullSelector = function () ( var path = this.parents().addBack(); var quickCss = path.get().map(function (item) ( var self = $(item), id = item .id ? "#" + item.id: "", clss = item.classList.length ? item.classList.toString().split(" ").map(function (c) ( return "." + c; )).join("") : "", nazwa = item.nodeName.toLowerCase(), index = self.siblings(name).length ? ":nth-child(" + (self.index() + 1) + ")" : ""; if (name === "html" || name === "body") ( zwraca nazwę; ) zwraca nazwę + index + id + clss; )).join("> ") ;zwróć quickCss;;

Możesz go użyć w ten sposób:

Console.log($("jakiś-selektor").fullSelector());

Przeniosłem fragment z T.J. Crowder do maleńkiej wtyczki jQuery. Użyłem wersji jQuery, nawet jeśli ma rację, jest to całkowicie niepotrzebne obciążenie, ale używam go tylko do celów debugowania, więc nie obchodzi mnie to.

Stosowanie:

zagnieżdżona rozpiętość
prosta rozpiętość
Przed

// wynik (tablica): ["body", "div.sampleClass"] $("span").getDomPath(false) // wynik (ciąg): body > div.sampleClass $("span").getDomPath( ) // wynik (tablica): ["body", "div#test"] $("pre").getDomPath(false) // wynik (string): body > div#test $("pre").getDomPath ()

var obj = $("#pokaż-przycisk-edytora"), ścieżka = ""; while (typeof obj.prop("nazwaznacznika") != "undefined")( if (obj.attr("klasa"))( ścieżka = "."+obj.attr("klasa").replace(/\s /g , ".") + ścieżka; ) if (obj.attr("id"))( ścieżka = "#"+obj.attr("id") + ścieżka; ) ścieżka = " " +obj.prop( "tagName").toLowerCase() + ścieżka; obj = obj.parent(); ) console.log(ścieżka);

cześć ta funkcja rozwiązuje błąd związany z brakiem bieżącego elementu w ścieżce

Sprawdź to teraz

$j(".wrapper").click(function(event) ( selectedElement=$j(event.target); var rightArrowParents = ; $j(event.target).parents().not("html,body") .each(function() ( var wpis = this.tagName.toLowerCase(); if (this.className) ( wpis += "." + this.className.replace(/ /g, "."); )else if (this.id)( wpis += "#" + this.id; ) entry=replaceAll(entry,"..","."); rightArrowParents.push(entry; )); rightArrowParents.reverse(); //if(event.target.nodeName.toLowerCase()=="a" || event.target.nodeName.toLowerCase()=="h1")( var entry = event.target.nodeName.toLowerCase(); if (event.target.className) ( wpis += "." + event.target.className.replace(/ /g, "."); )else if(event.target.id)( entry += "#" + event.target.id; ) rightArrowParents.push(entry); // )

Gdzie $j = jQuery Variable

rozwiąż również problem z .. w nazwie klasy

oto funkcja replace:

Funkcja escapeRegExp(str) ( return str.replace(/([.*+?^=!:$()()|\[\]\/\\])/g, "\\$1"); ) funkcja replaceAll(str, find, replace) ( return str.replace(new RegExp(escapeRegExp(find), "g"), replace); )

Oto natywna wersja JS, która zwraca ścieżkę jQuery. Dodaję również identyfikatory elementów, jeśli takie istnieją. To da ci możliwość wybrania najkrótszej ścieżki, jeśli zobaczysz identyfikator w tablicy.

varpath = getDomPath(element); console.log(ścieżka.join("> "));

Treść > section:eq(0) > div:eq(3) > section#content > section#firehose > div#firehoselist > article#firehose-46813651 > header > h2 > span#title-46813651

Oto funkcja.

Funkcja getDomPath(el) ( var stack = ; while (el.parentNode != null) ( console.log(el.nodeName); var sibCount = 0; var sibIndex = 0; for (var i = 0; i< el.parentNode.childNodes.length; i++) { var sib = el.parentNode.childNodes[i]; if (sib.nodeName == el.nodeName) { if (sib === el) { sibIndex = sibCount; } sibCount++; } } if (el.hasAttribute("id") && el.id != "") { stack.unshift(el.nodeName.toLowerCase() + "#" + el.id); } else if (sibCount >1) ( stack.unshift(el.nodeName.toLowerCase() + ":eq(" + sibIndex + ")"); ) else ( stack.unshift(el.nodeName.toLowerCase()); ) el = el.parentNode ; ) zwraca stos.wycinek(1); // usuwa element html )

W dzisiejszych czasach powszechne stały się złożone i ciężkie aplikacje internetowe. Wiele przeglądarek i łatwe w użyciu biblioteki, takie jak jQuery, z ich szeroką funkcjonalnością mogą znacznie pomóc w manipulowaniu DOM w locie. Dlatego nie dziwi fakt, że wielu programistów korzysta z takich bibliotek częściej niż pracuje z natywnym API DOM, które miało sporo problemów. I choć różnice w przeglądarkach nadal stanowią problem, DOM jest teraz w lepszej formie niż 5-6 lat temu, kiedy jQuery zyskiwało na popularności.

W tym artykule zademonstruję zdolność DOM do manipulowania HTML, skupiając się na relacjach między rodzicami, dziećmi i sąsiadami. Zakończę omówieniem obsługi tych funkcji przez przeglądarki, ale pamiętaj, że biblioteka typów jQuery jest nadal dobrym rozwiązaniem ze względu na błędy i niespójności w implementacji natywnej funkcjonalności.

Liczenie węzłów podrzędnych

Do demonstracji użyję następujących znaczników HTML, które zmienimy kilka razy w całym artykule:

  • Przykład pierwszy
  • przykład drugi
  • przykład trzeci
  • przykład czwarty
  • przykład piąty
  • Przykład szósty

Var mojaLista = document.getElementById("mojaLista"); console.log(mojaLista.dzieci.length); // 6 console.log(myList.childElementCount); // 6

Jak widać, wyniki są takie same, chociaż stosowane techniki są inne. W pierwszym przypadku korzystam z własności dzieci. Jest to właściwość tylko do odczytu i zwraca kolekcję elementy HTML, znajdujący się wewnątrz żądanego elementu; aby policzyć ich liczbę, używam właściwości length tej kolekcji.

W drugim przykładzie używam metody childElementCount, którą uważam za bardziej przejrzysty i potencjalnie łatwiejszy w utrzymaniu sposób (więcej o tym później, nie sądzę, że będziesz miał problem ze zrozumieniem, co robi).

Mógłbym spróbować użyć childNodes.length (zamiast children.length), ale spójrz na wynik:

Var mojaLista = document.getElementById("mojaLista"); console.log(myList.childNodes.length); // 13

Zwraca 13, ponieważ childNodes jest zbiorem wszystkich węzłów, w tym spacji — pamiętaj o tym, jeśli zależy Ci na różnicy między węzłami podrzędnymi a węzłami elementów podrzędnych.

Sprawdzanie istnienia węzłów podrzędnych

Aby sprawdzić, czy element ma węzły podrzędne, mogę użyć metody hasChildNodes(). Metoda zwraca logiczne wskazanie ich obecności lub nieobecności:

Var mojaLista = document.getElementById("mojaLista"); console.log(mojaLista.hasChildNodes()); // PRAWDA

Wiem, że moja lista zawiera węzły podrzędne, ale mogę zmienić kod HTML, aby ich nie było; teraz znacznik wygląda tak:

A oto wynik ponownego uruchomienia hasChildNodes():

Console.log(mojaLista.hasChildNodes()); // PRAWDA

Metoda nadal zwraca true . Chociaż lista nie zawiera żadnych elementów, zawiera spację, która jest prawidłowym typem węzła. Ta metoda uwzględnia wszystkie węzły, a nie tylko węzły elementów. Aby hasChildNodes() zwróciło wartość false, musimy ponownie zmienić znacznik:

A teraz oczekiwany wynik wyświetla się w konsoli:

Console.log(mojaLista.hasChildNodes()); // fałszywy

Oczywiście, jeśli wiem, że mogę napotkać spację, najpierw sprawdzam, czy istnieją węzły podrzędne, a następnie używam właściwości nodeType, aby określić, czy są wśród nich węzły elementów.

Dodawanie i usuwanie elementów podrzędnych

Istnieją techniki, które można wykorzystać do dodawania i usuwania elementów z DOM. Najsłynniejsza z nich opiera się na połączeniu metod createElement() i appendChild().

VarmyEl = document.createElement("div"); document.body.appendChild(myEl);

W tym przypadku tworzę

za pomocą metody createElement() , a następnie dodając ją do body . Bardzo proste i prawdopodobnie używałeś tej techniki wcześniej.

Ale zamiast wstawiać specjalnie spreparowany element, mogę również użyć appendChild() i po prostu przenieść istniejący element. Załóżmy, że mamy następujący znacznik:

  • Przykład pierwszy
  • przykład drugi
  • przykład trzeci
  • przykład czwarty
  • przykład piąty
  • Przykład szósty

przykładowy tekst

Mogę zmienić lokalizację listy następującym kodem:

Var mojaLista = document.getElementById("mojaLista"), container = document.getElementById("c"); container.appendChild(mojaLista);

Ostateczny DOM będzie wyglądał tak:

przykładowy tekst

  • Przykład pierwszy
  • przykład drugi
  • przykład trzeci
  • przykład czwarty
  • przykład piąty
  • Przykład szósty

Zauważ, że cała lista została usunięta z jej miejsca (nad akapitem), a następnie wstawiona po niej, przed treścią zamykającą . Chociaż metoda appendChild() jest zwykle używana do dodawania elementów utworzonych za pomocą metody createElement() , może być również używana do przenoszenia istniejących elementów.

Mogę również całkowicie usunąć element podrzędny z DOM za pomocą removeChild() . Oto jak nasza lista została usunięta z poprzedniego przykładu:

Var mojaLista = document.getElementById("mojaLista"), container = document.getElementById("c"); container.removeChild(mojaLista);

Element został usunięty. Metoda removeChild() zwraca usunięty element i mogę go przechowywać w razie potrzeby później.

Var mojeStareDziecko = document.body.removeChild(mojaLista); document.body.appendChild(mojeStareDziecko);

Istnieje również metoda ChildNode.remove(), stosunkowo niedawno dodana do specyfikacji:

Var mojaLista = document.getElementById("mojaLista"); mojaLista.usuń();

Ta metoda nie zwraca obiektu zdalnego i nie działa w IE (tylko Edge). Obie metody usuwają węzły tekstowe w taki sam sposób, jak węzły elementów.

Wymiana elementów podrzędnych

Mogę zastąpić istniejący element potomny nowym, niezależnie od tego, czy nowy element istnieje, czy też stworzyłem go od podstaw. Oto znacznik:

przykładowy tekst

Var myPar = document.getElementById("par"), myDiv = document.createElement("div"); myDiv.className = "przykład"; myDiv.appendChild(document.createTextNode("Tekst nowego elementu")); document.body.replaceChild(myDiv, myPar);

Tekst nowego elementu

Jak widać, metoda replaceChild() przyjmuje dwa argumenty: nowy element i stary element, który zastępuje.

Mogę również użyć tej metody do przeniesienia istniejącego elementu. Spójrz na następujący kod HTML:

przykładowy tekst 1

przykładowy tekst 2

przykładowy tekst 3

Mogę zastąpić trzeci akapit pierwszym akapitem następującym kodem:

Var myPar1 = document.getElementById("par1"), myPar3 = document.getElementById("par3"); document.body.replaceChild(mojpar1, mojpar3);

Teraz wygenerowany DOM wygląda tak:

przykładowy tekst 2

przykładowy tekst 1

Wybieranie określonych elementów podrzędnych

Istnieje kilka różne sposoby wybór konkretnego elementu. Jak pokazano wcześniej, mogę zacząć od użycia kolekcji children lub właściwości childNodes. Spójrzmy jednak na inne opcje:

Właściwości firstElementChild i lastElementChild robią dokładnie to, czego można oczekiwać od ich nazwy: wybierają pierwszy i ostatni element podrzędny. Wróćmy do naszych znaczników:

  • Przykład pierwszy
  • przykład drugi
  • przykład trzeci
  • przykład czwarty
  • przykład piąty
  • Przykład szósty

Mogę wybrać pierwszy i ostatni element o tych właściwościach:

Var mojaLista = document.getElementById("mojaLista"); console.log(myList.firstElementChild.innerHTML); // „Przykład pierwszy” console.log(myList.lastElementChild.innerHTML); // "Przykład szósty"

Mogę również użyć właściwości previousElementSibling i nextElementSibling, jeśli chcę wybrać elementy podrzędne inne niż pierwszy lub ostatni. Odbywa się to poprzez połączenie właściwości firstElementChild i lastElementChild:

Var mojaLista = document.getElementById("mojaLista"); console.log(myList.firstElementChild.nextElementSibling.innerHTML); // „Przykład drugi” console.log(myList.lastElementChild.previousElementSibling.innerHTML); // "Przykład piąty"

Istnieją również podobne właściwości firstChild , lastChild , previousSibling i nextSibling , ale uwzględniają one wszystkie typy węzłów, a nie tylko elementy. Ogólnie właściwości uwzględniające tylko węzły elementów są bardziej przydatne niż te, które wybierają wszystkie węzły.

Wstawianie treści do DOM

Przyjrzałem się już sposobom wstawiania elementów do DOM. Przejdźmy do podobnego tematu i przyjrzyjmy się nowym funkcjom wstawiania treści.

Po pierwsze, istnieje prosta metoda insertBefore(), która jest bardzo podobna do replaceChild() , przyjmuje dwa argumenty i działa zarówno na nowych, jak i istniejących elementach. Oto znacznik:

  • Przykład pierwszy
  • przykład drugi
  • przykład trzeci
  • przykład czwarty
  • przykład piąty
  • Przykład szósty

Przykładowy akapit

Zwróć uwagę na akapit, najpierw go usunę, a następnie wstawię przed listą, wszystko za jednym zamachem:

Var mojaLista = document.getElementById("mojaLista"), container = document.getElementBy("c"), mojaPar = document.getElementById("par"); container.insertBefore(myPar, mojaLista);

W wynikowym kodzie HTML akapit pojawi się przed listą i jest to kolejny sposób na zawinięcie elementu.

Przykładowy akapit

  • Przykład pierwszy
  • przykład drugi
  • przykład trzeci
  • przykład czwarty
  • przykład piąty
  • Przykład szósty

Podobnie jak replaceChild() , insertBefore() przyjmuje dwa argumenty: element do dodania i element przed którym chcemy go wstawić.

Ta metoda jest prosta. Wypróbujmy teraz bardziej wydajny sposób wstawiania: metodę insertAdjacentHTML().