ТÑнÑовий DOM (âShadow DOMâ) викоÑиÑÑовÑÑÑÑÑÑ Ð´Ð»Ñ ÑнкапÑÑлÑÑÑÑ. ÐÑн дозволÑÑ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½ÑÑ Ð¼Ð°Ñи ÑÐ²Ð¾Ñ Ð²Ð»Ð°Ñне âÑÑнÑовеâ DOM-деÑево, Ñо не може бÑÑи випадково змÑнено з головного докÑменÑÑ, a Ñакож може маÑи влаÑÐ½Ñ Ð»Ð¾ÐºÐ°Ð»ÑÐ½Ñ ÑÑилÑ, Ñа Ñн.
ÐбÑдований ÑÑнÑовий DOM
Чи замиÑлÑвалиÑÑ Ð²Ð¸ коли-небÑдÑ, Ñк влаÑÑÐ¾Ð²Ð°Ð½Ñ Ñа ÑÑилÑÐ·Ð¾Ð²Ð°Ð½Ñ ÑÐºÐ»Ð°Ð´Ð½Ñ Ð±ÑаÑзеÑÐ½Ñ ÑнÑеÑакÑÐ¸Ð²Ð½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи?
Ð¢Ð°ÐºÑ Ñк <input type="range">:
ÐÑаÑÐ·ÐµÑ Ð²Ð¸ÐºÐ¾ÑиÑÑовÑÑ DOM/CSS на ÑвÑй ÑозÑÑд, Ñоб вÑдобÑазиÑи ÑÑ . Така ÑÑÑÑкÑÑÑа DOM зазвиÑай пÑÐ¸Ñ Ð¾Ð²Ð°Ð½Ð° вÑд наÑ, але ми можемо ÑÑ Ð¿Ð¾Ð±Ð°ÑиÑи в ÑнÑÑÑÑменÑÐ°Ñ ÑозÑобника. ÐапÑиклад, Ñ Chrome нам знадобиÑÑÑÑ Ð°ÐºÑивÑваÑи опÑÑÑ âShow user agent shadow DOMâ.
ÐÑже, <input type="range"> виглÑÐ´Ð°Ñ Ñак:
Те, Ñо вÑдобÑажено пÑд #shadow-root Ñ Ñ âÑÑнÑовим DOMâ (shadow DOM).
Ðи не можемо оÑÑимаÑи доÑÑÑп до ÑÑнÑового DOM вбÑÐ´Ð¾Ð²Ð°Ð½Ð¸Ñ ÐµÐ»ÐµÐ¼ÐµÐ½ÑÑв звиÑайними заÑобами JavaScript Ñи за Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ ÑелекÑоÑÑв. Це не пÑоÑÑо доÑÑÑÐ½Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи, а поÑÑжний ÑпоÑÑб ÑнкапÑÑлÑÑÑÑ, ÑобÑо Ð·Ð°Ñ Ð¸ÑÑÑ Ð²Ñд зовнÑÑнÑого вÑÑÑÑÐ°Ð½Ð½Ñ Ñ Ð²Ð½ÑÑÑÑÑÐ½Ñ ÑÑÑÑкÑÑÑÑ.
У виÑÐµÐ½Ð°Ð²ÐµÐ´ÐµÐ½Ð¾Ð¼Ñ Ð¿ÑÐ¸ÐºÐ»Ð°Ð´Ñ Ð·Ð²ÐµÑнÑÑÑ ÑÐ²Ð°Ð³Ñ Ð½Ð° коÑиÑний аÑÑибÑÑ pseudo. ÐÑн Ñ Ð½ÐµÑÑандаÑÑним Ñа ÑÑнÑÑ ÑеÑез ÑÑÑоÑиÑÐ½Ñ Ð¿ÑиÑини. Ðого можна викоÑиÑÑовÑваÑи Ð·Ð°Ð´Ð»Ñ ÑÑилÑзаÑÑÑ Ð²ÐºÐ»Ð°Ð´ÐµÐ½Ð¸Ñ
елеменÑÑв ÑеÑез CSS, напÑиклад, Ñак:
<style>
/* Ñобимо ÑÐ»Ð°Ð¹Ð´ÐµÑ Ð¿Ð¾Ð²Ð·Ñнка ÑеÑвоним */
input::-webkit-slider-runnable-track {
background: red;
}
</style>
<input type="range">
ÐаголоÑÑÑмо, pseudo Ñ Ð½ÐµÑÑандаÑÑним аÑÑибÑÑом. ÐÑÑоÑиÑно, бÑаÑзеÑи ÑпоÑаÑÐºÑ Ð¿Ð¾Ñали екÑпеÑименÑÑваÑи Ð·Ñ Ð²Ð½ÑÑÑÑÑнÑми DOM-ÑÑÑÑкÑÑÑами Ð´Ð»Ñ ÑÑвоÑÐµÐ½Ð½Ñ ÑнÑеÑакÑивниÑ
елеменÑÑв, Ñ ÑÑлÑки поÑÑм, ÑеÑез певний ÑаÑ, ÑÑнÑовий DOM бÑло ÑÑандаÑÑизовано, Ñоб надаÑи можливÑÑÑÑ Ð½Ð°Ð¼, ÑозÑобникам, ÑобиÑи Ñе Ñаме.
ÐÐ°Ð´Ð°Ð»Ñ Ð¼Ð¸ викоÑиÑÑовÑваÑимемо ÑÑÑаÑний ÑÑнÑовий ÑÑандаÑÑ DOM, вÑдобÑажений Ñ DOM ÑпеÑиÑÑкаÑÑÑ Ñа в ÑнÑÐ¸Ñ ÑпоÑÑÐ´Ð½ÐµÐ½Ð¸Ñ ÑпеÑиÑÑкаÑÑÑÑ .
ТÑнÑове деÑево
DOM-ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð¼Ð¾Ð¶Ðµ маÑи два Ñипи DOM пÑддеÑев:
- Light tree â звиÑайне âcвÑÑлеâ DOM пÑддеÑево, Ñо ÑкладаÑÑÑÑÑ Ð· HTML-наÑадкÑв. УÑÑ Ð¿ÑддеÑева, пÑо ÑÐºÑ Ð¹ÑлоÑÑ Ñ Ð¿Ð¾Ð¿ÐµÑеднÑÑ ÑоздÑÐ»Ð°Ñ , бÑли âcвÑÑлÑâ.
- Shadow tree â пÑÐ¸Ñ Ð¾Ð²Ð°Ð½Ðµ âÑÑнÑовеâ DOM пÑддеÑево, не вÑдобÑажене Ñ HTML Ñа ÑÑ Ð¾Ð²Ð°Ð½Ðµ вÑд ÑÑоÑоннÑÑ Ð¾Ñей.
ЯкÑо ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð¼Ð°Ñ Ð¾Ð±Ð¸Ð´Ð²Ð°, Ñо бÑаÑÐ·ÐµÑ Ð²ÑдобÑÐ°Ð¶Ð°Ñ ÑÑлÑки ÑÑнÑове деÑево. Також ми можемо вÑÑановиÑи певний вид композиÑÑÑ (взаÑмодÑÑ) мÑж ÑÑнÑовим Ñа ÑвÑÑлим деÑевами. Ðи обговоÑимо ÑÑ Ð´ÐµÑÐ°Ð»Ñ Ð½Ð°Ð´Ð°Ð»Ñ Ñ ÑоздÑÐ»Ñ Ð¡Ð»Ð¾Ñи ÑÑнÑового DOM, композиÑÑÑ.
ТÑнÑове деÑево може бÑÑи викоÑиÑÑаним в коÑиÑÑÑваÑÑÐºÐ¸Ñ ÐµÐ»ÐµÐ¼ÐµÐ½ÑÐ°Ñ (Ñustom elements), Ñоб пÑÐ¸Ñ Ð¾Ð²Ð°Ñи внÑÑÑÑÑÐ½Ñ ÑÑÑÑкÑÑÑÑ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñа Ñ Ð·Ð°ÑÑоÑÑваÑи до нÑого локалÑÐ½Ñ ÑÑилÑ, Ð·Ð°Ñ Ð¸ÑÐµÐ½Ñ Ð²Ñд зовнÑÑнÑого вÑÑÑÑаннÑ.
ÐапÑиклад, Ñей <show-hello> ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð¿ÑиÑ
овÑÑ ÑвÑй внÑÑÑÑÑнÑй DOM Ñ ÑÑнÑÐ¾Ð²Ð¾Ð¼Ñ Ð´ÐµÑевÑ:
<script>
customElements.define('show-hello', class extends HTMLElement {
connectedCallback() {
const shadow = this.attachShadow({mode: 'open'});
shadow.innerHTML = `<p>
Hello, ${this.getAttribute('name')}
</p>`;
}
});
</script>
<show-hello name="John"></show-hello>
ÐÑÑ Ñак оÑÑиманий DOM виглÑÐ´Ð°Ñ Ð² ÑнÑÑÑÑменÑÐ°Ñ ÑозÑобника Chrome, ÑвеÑÑ ÐºÐ¾Ð½ÑÐµÐ½Ñ Ð²ÑеÑÐµÐ´Ð¸Ð½Ñ â#shadow-rootâ:
Ðо-пеÑÑе, виклик elem.attachShadow({mode: â¦}) ÑÑвоÑÑÑ ÑÑнÑове деÑево.
ÐÑнÑÑ Ð´Ð²Ð° обмеженнÑ:
- ÐÐ»Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ елеменÑÑ Ð¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾ ÑÑвоÑиÑи ÑÑлÑки один ÑÑнÑовий root.
elemповинен бÑÑи або каÑÑомним елеменÑом, або одним з наÑÑÑÐ¿Ð½Ð¸Ñ : âarticleâ, âasideâ, âblockquoteâ, âbodyâ, âdivâ, âfooterâ, âh1â¦h6â, âheaderâ, âmainâ ânavâ, âpâ, âsectionâ, or âspanâ. ÐнÑÑ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи, ÑÐ°ÐºÑ Ñк<img>, не можÑÑÑ Ð¼ÑÑÑиÑи ÑÑнÑове деÑево.
ÐпÑÑÑ mode вÑÑановлÑÑ ÑÑÐ²ÐµÐ½Ñ ÑнкапÑÑлÑÑÑÑ, вона повинна маÑи одне з двоÑ
знаÑенÑ:
-
"open"â ÑÑнÑовий root доÑÑÑпний Ñкelem.shadowRoot.ÐÑдÑ-Ñкий код Ð¼Ð°Ñ Ð´Ð¾ÑÑÑп до ÑÑнÑового деÑева
elem. -
"closed"âelem.shadowRootзавждиnull.Ðи можемо оÑÑимаÑи доÑÑÑп до ÑÑнÑового DOM ÑÑлÑки по поÑиланнÑ, Ñке повеÑÑаÑÑÑÑÑ
attachShadow(Ñ, можливо, пÑÐ¸Ñ Ð¾Ð²Ð°Ð½Ðµ Ñ ÐºÐ»Ð°ÑÑ). ÐбÑÐ´Ð¾Ð²Ð°Ð½Ñ Ð±ÑаÑзеÑÐ½Ñ Ð½Ð°ÑÐ¸Ð²Ð½Ñ Ð´ÐµÑева, ÑакÑ, Ñк<input type="range">, Ñ Ð·Ð°ÐºÑиÑими, до Ð½Ð¸Ñ Ð½Ðµ дÑÑÑаÑиÑÑ.
ТÑнÑовий root, Ñкий повеÑÑÐ°Ñ attachShadow, поводиÑÑÑÑ Ñк елеменÑ: ми можемо викоÑиÑÑовÑваÑи innerHTML Ñи DOM-меÑоди, ÑÐ°ÐºÑ Ñк append, Ñоб заповниÑи його.
ÐÐ»ÐµÐ¼ÐµÐ½Ñ Ð· ÑÑнÑового root називаÑÑÑÑÑ âshadow tree hostâ Ñ Ð´Ð¾ÑÑÑпний Ñк влаÑÑивÑÑÑÑ host Ñ shadow root.
// за Ñмови {mode: "open"}, ÑнакÑе elem.shadowRoot Ñе null
alert(elem.shadowRoot.host === elem); // true
ÐнкапÑÑлÑÑÑÑ
ТÑнÑовий DOM ÑÑлковиÑо вÑдокÑемлений вÑд оÑновного докÑменÑÑ:
- ÐлеменÑи ÑÑнÑового DOM Ð½ÐµÐ²Ð¸Ð´Ð¸Ð¼Ñ Ð´Ð»Ñ
querySelectorÐ·Ñ ÑвÑÑлого DOM. ÐокÑема, ÑÑнÑовий DOM ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ð¼Ð¾Ð¶Ðµ маÑи вÑеÑÐµÐ´Ð¸Ð½Ñ Ð°ÑÑибÑÑиidÐ·Ñ Ð·Ð½Ð°ÑеннÑми, Ñо конÑлÑкÑÑÑÑÑ Ð· однойменними Ð·Ñ ÑвÑÑлого DOM. Ðони Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ Ð±ÑÑи ÑнÑкалÑними ÑÑлÑки вÑеÑÐµÐ´Ð¸Ð½Ñ ÑÑнÑового деÑева. - ТÑнÑовий DOM Ð¼Ð°Ñ Ð²Ð»Ð°ÑÐ½Ñ ÑÑилÑ. СÑилÑÐ¾Ð²Ñ Ð¿Ñавила з зовнÑÑнÑого DOM не заÑÑоÑовÑÑÑÑÑÑ.
ÐапÑиклад:
<style>
/* ÑÑÐ¸Ð»Ñ Ð´Ð¾ÐºÑменÑа не заÑÑоÑовÑÑÑÑÑÑ Ð´Ð¾ ÑÑнÑового деÑева вÑеÑÐµÐ´Ð¸Ð½Ñ #elem (1) */
p { color: red; }
</style>
<div id="elem"></div>
<script>
elem.attachShadow({mode: 'open'});
// ÑÑнÑове деÑево Ð¼Ð°Ñ Ð²Ð»Ð°ÑÐ½Ñ ÑÑÐ¸Ð»Ñ (2)
elem.shadowRoot.innerHTML = `
<style> p { font-weight: bold; } </style>
<p>Hello, John!</p>
`;
// <p> видимий ÑÑлÑки запиÑам зÑеÑедини ÑÑнÑового деÑева (3)
alert(document.querySelectorAll('p').length); // 0
alert(elem.shadowRoot.querySelectorAll('p').length); // 1
</script>
- СÑÐ¸Ð»Ñ Ð³Ð¾Ð»Ð¾Ð²Ð½Ð¾Ð³Ð¾ докÑменÑÑ Ð½Ðµ впливаÑÑÑ Ð½Ð° ÑÑнÑове деÑево.
- â¦Ðле ÑÑÐ¸Ð»Ñ Ð·ÑеÑедини пÑаÑÑÑÑÑ.
- Щоб дÑÑÑаÑиÑÑ ÐµÐ»ÐµÐ¼ÐµÐ½ÑÑв ÑÑнÑового деÑева, Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ виконÑваÑиÑÑ Ð·ÑеÑедини деÑева.
ÐовÑдки
- DOM: https://dom.spec.whatwg.org/#shadow-trees
- СÑмÑÑнÑÑÑÑ: https://caniuse.com/#feat=shadowdomv1
- ТÑнÑовий DOM згадÑÑÑÑÑÑ Ñ Ð±Ð°Ð³Ð°ÑÑоÑ
ÑнÑиÑ
ÑпеÑиÑÑкаÑÑÑÑ
, напÑиклад, DOM Parsing вказÑÑ Ð½Ð° Ñе, Ñо Ñ shadow root Ñ
innerHTML.
ÐÑдÑÑмки
ТÑнÑовий DOM â Ñе ÑпоÑÑб ÑÑвоÑиÑи ÑзолÑоване DOM-деÑево Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñа.
shadowRoot = elem.attachShadow({mode: open|closed})â ÑÑвоÑÑÑ ÑÑнÑовий DOM длÑelem. ЯкÑоmode="open", Ñо вÑн Ñ Ð´Ð¾ÑÑжним Ñк влаÑÑивÑÑÑÑelem.shadowRoot.- Ðи можемо запиÑаÑи ÑоÑÑ Ð²ÑеÑединÑ
shadowRoot, викоÑиÑÑовÑÑÑиinnerHTMLÑи ÑнÑÑ DOM-меÑоди.
ТÑнÑÐ¾Ð²Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñи DOM:
- ÐаÑÑÑ Ð¾ÐºÑÐµÐ¼Ñ Ð¾Ð±Ð»Ð°ÑÑÑ Ð´Ð»Ñ ÑнÑкалÑноÑÑÑ Ð·Ð½Ð°ÑÐµÐ½Ñ Ð² аÑÑибÑÑаÑ
idHTML-елеменÑÑв, - ÐÐµÐ²Ð¸Ð´Ð¸Ð¼Ñ Ð´Ð»Ñ ÑелекÑоÑÑв JavaScript з головного докÑменÑÑ, Ñаким меÑодам, Ñк
querySelector; - ÐикоÑиÑÑовÑÑÑÑ ÑÑÐ¸Ð»Ñ ÑÑлÑки з ÑÑнÑового деÑева, а не глобалÑÐ½Ñ ÑÑÐ¸Ð»Ñ Ð´Ð¾ÐºÑменÑÑ.
ТÑнÑовий DOM, ÑкÑо ÑÑнÑÑ, ÑендеÑиÑÑÑÑ Ð±ÑаÑзеÑом замÑÑÑÑ Ñак званого âÑвÑÑлого DOMâ (звиÑÐ°Ð¹Ð½Ð¸Ñ Ð½Ð°ÑадкÑв). У Ð³Ð»Ð°Ð²Ñ Ð¡Ð»Ð¾Ñи ÑÑнÑового DOM, композиÑÑÑ Ð¼Ð¸ ÑозбеÑемо, Ñк поÑднÑваÑи ÑÑ .
ÐоменÑаÑÑ
<code>, Ð´Ð»Ñ ÐºÑлÑÐºÐ¾Ñ ÑÑдкÑв â обгоÑнÑÑÑ ÑÑ Ñегом<pre>, Ð´Ð»Ñ Ð¿Ð¾Ð½Ð°Ð´ 10 ÑÑдкÑв â викоÑиÑÑовÑйÑе пÑÑоÑниÑÑ (plnkr, jsbin, codepenâ¦)