DOM
SGML-like trees, но больше заточен под HTML, SVG/XML.
DOM API довольно крутой у нас.
Времена, когда нужен был jQuery, чтобы фиксить несовместимости уже прошли. Еще со времен ie10.
spec link whatwg
idl spec для расшифровки
Понятие BOM - не корректно, все, что есть в браузере разбросано по большому количеству стандартов.
Наследование
class EventTarget {
addEventListener() {}
removeEventListener() {}
dispatchEvent() {} // возвращает boolean - удачно или нет
}
document.createelement('select')
select.__proto__
HTMLSelectElement.__proto__
HTMLElement.__proto__
Element.__proto__
Node.__proto__
EventTarget.__proto__
Object
addEventListener
addEventListener(type, object, options)
"click", "animationend", "input"
{
handleEvent() {}
}
options {
capture: true/false,
passive: true/false (новая штука) - сказать, что preventDefault не будет и можно выполнять код параллельно например с wheel
once: true/false (новая штука)
}
new Event("click", {bubbles: true})
eventPhase 0
eventPhase 1 - capture
eventPhase 2 - event.target
eventPhase 3 - bubbles
current.target == this
На window не слушать ничего, кроме ресайза и скрола, остальное на document
preventDefault
stopPropagation
stopImmediatePropagation
Node
Node.prototype.nodeType - возвращает константу типа
1 - element
3 - text node
8 - comment
11 - document fragment
someNode.contains(child) // true если содержит ребенка или сам попадает
appendChild // this
removeChild // removed
insertBefore(before, what) если null - то appendChild
replaceChild(new, old) // return old
after // принимает строку, либо ноды, строку обернет в текстовый узел
before
replaceWith
remove
append
prepend
все возвращают undefined
children, siblings, descendant - названия
childNodes, children
firstElementChild, lastElementChild, nextElementSibling
closest(selector), matches(selector)
attrs (начальное) vs IDL props (текущее значение)
innerHTML/outerHTML
Возможна утечка памяти
НЕ ПИСАТЬ ТАК!!!
innerHTML +=
замена элементов на такие же, вызывать коллбеки (на кастомных элементах например), если остались ссылки, то они будут ссылаться на эл, которые уже вне дома и т.д.
insertAdjacentHTML лучше юзать
Вместо className юзать classList
Iterator есть:
- NodeList
- HTMLCollection
- NodeTokenList
- .attributes
Разница между NodeList и HTMLCollection.
При document.querySelectorAll - NodeList, не является массивом и инстансом массива. Static.
Делаем Array.from, [ ...document ]
fragments Раньше были проблеммы с производительностью, когда вставляли элементы по одному, поэтому нужен был createDocumentFragment. Можно юзать.
template.content.closeNode(true)
dataset
dataset
var smth = el.getAttribute('data-smth')
var {smth, camelCase, id} = el.dataset // camelCase будет camel-case
delete el.dataset.id
query/queryAll, Elements < Array
Возвращает obj instanceof Elements extends Array
document.queryAll(selectorA).map(...).queryAll()
custom events
new CustomEvent(type, {
bubbles, cancelable, detail: {
}
})
не надо писать
document.createEvent()
.initMouseEvent(...)
юзать конструкторы
new Document
new Text
new Event
mutation events vs observers
events не юзать (выпиливаются из движков) - проблема в синхронности
new MutationObserver(records => {
}).observe(node, {
attributes: true,
attributeFilter: [ "data-smth" ]
})
custom elements
Чтобы сделать в том числе разметку более читаемой
<hangout-message>
могут экстендить другие элементы (лучше писать так, чтобы было семантическое значение и было проще реюзать методы)
<article is=hangout-message>
</article>
<button is=send-message>
</button>
Регистрация
document.registerElement("name", {
extends: "dialog",
prototype: Object.create(HTMLDialogElement.prototype)
})
customElements.define('name', class extends HTMLDialogElement {
constructor() {
super(...arguments)
// не писать много логики, выполняется, когда парсер встретил в html
// не полагаться, что у элемента есть родитель, дети
}
connectedCallback() {
// лоигка и слушатели тут в disconnectedCallback убирать слушатели
}
attributeChangedCallback() {}
})
Есть библиотеки, вроде Polymer
WEB components
- html imports
- shadow dom
- custom elements
web components in React
<dialog is=react-ready
open={state.dialog}
modal={true}
anchor={state.pokemon}
>
</dialog>
ShadowDOM
продвинутый способ инкапсулировать внутри компонента логику и стили
все, что внутри стилей будет применено только к компоненту
<link rel=import href=component.html>
<template>
<link rel=stylesheet href=...>
</template>
<script>
...
</script>