JavaScript'te Shadow DOM

JavaScript'te Shadow DOM

Bu makale, JavaScript'te Shadow DOM'u açıklar.

YouTube Video

javascript-html-shadow-dom.html
  1<!DOCTYPE html>
  2<html lang="en">
  3<head>
  4  <meta charset="UTF-8">
  5  <title>JavaScript &amp; HTML</title>
  6  <style>
  7    * {
  8        box-sizing: border-box;
  9    }
 10
 11    body {
 12        margin: 0;
 13        padding: 1em;
 14        padding-bottom: 10em;
 15        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
 16        background-color: #f7f9fc;
 17        color: #333;
 18        line-height: 1.6;
 19    }
 20
 21    .container {
 22        max-width: 800px;
 23        margin: 0 auto;
 24        padding: 1em;
 25        background-color: #ffffff;
 26        border: 1px solid #ccc;
 27        border-radius: 10px;
 28        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
 29    }
 30
 31    h1, h2 {
 32        font-size: 1.2rem;
 33        color: #007bff;
 34        margin-top: 0.5em;
 35        margin-bottom: 0.5em;
 36        border-left: 5px solid #007bff;
 37        padding-left: 0.6em;
 38        background-color: #e9f2ff;
 39    }
 40
 41    button {
 42        display: block;
 43        margin: 1em auto;
 44        padding: 0.75em 1.5em;
 45        font-size: 1rem;
 46        background-color: #007bff;
 47        color: white;
 48        border: none;
 49        border-radius: 6px;
 50        cursor: pointer;
 51        transition: background-color 0.3s ease;
 52    }
 53
 54    button:hover {
 55        background-color: #0056b3;
 56    }
 57
 58    #output {
 59        margin-top: 1em;
 60        background-color: #1e1e1e;
 61        color: #0f0;
 62        padding: 1em;
 63        border-radius: 8px;
 64        min-height: 200px;
 65        font-family: Consolas, monospace;
 66        font-size: 0.95rem;
 67        overflow-y: auto;
 68        white-space: pre-wrap;
 69    }
 70
 71    .highlight {
 72        outline: 3px solid #ffc107; /* yellow border */
 73        background-color: #fff8e1;  /* soft yellow background */
 74        transition: background-color 0.3s ease, outline 0.3s ease;
 75    }
 76
 77    .active {
 78        background-color: #28a745; /* green background */
 79        color: #fff;
 80        box-shadow: 0 0 10px rgba(40, 167, 69, 0.5);
 81        transition: background-color 0.3s ease, box-shadow 0.3s ease;
 82    }
 83  </style>
 84</head>
 85<body>
 86    <div class="container">
 87        <h2>HTML Sample</h2>
 88        <div id="content"></div>
 89        <div id="shadow-host">Shadow Root Element</div>
 90        <my-card></my-card>
 91    </div>
 92
 93    <div class="container">
 94        <h1>JavaScript Console</h1>
 95        <button id="executeBtn">Execute</button>
 96        <div id="output"></div>
 97    </div>
 98
 99    <div>
100        <h2>Slot Sample</h2>
101        <my-element>
102            <h3 slot="header">Header Content</h1>
103            <p slot="content">Main Content</p>
104        </my-element>
105    </div>
106
107    <script>
108        // Override console.log to display messages in the #output element
109        (function () {
110            const originalLog = console.log;
111            console.log = function (...args) {
112                originalLog.apply(console, args);
113                const output = document.getElementById('output');
114                output.textContent += args.map(String).join(' ') + '\n';
115            };
116        })();
117
118        document.getElementById('executeBtn').addEventListener('click', () => {
119            // Prevent multiple loads
120            if (document.getElementById('externalScript')) return;
121
122            const script = document.createElement('script');
123            script.src = 'javascript-html-shadow-dom.js';
124            script.id = 'externalScript';
125            //script.onload = () => console.log('javascript-html-shadow-dom.js loaded and executed.');
126            //script.onerror = () => console.log('Failed to load javascript-html-shadow-dom.js.');
127            document.body.appendChild(script);
128        });
129    </script>
130</body>
131</html>

Shadow DOM'u Anlamak

Shadow DOM, stiller ve DOM yapılarını bileşenler içinde kapsüllemenizi sağlayan Web Components standardının güçlü bir özelliğidir. Bu özellik, bileşenler ile ana belge arasındaki stil ve komut dosyası karışıklığını önler.

JavaScript'te Shadow DOM

Shadow DOM, normal bir DOM elementine bağlanan sınırlandırılmış bir DOM ağacı oluşturmanın bir yolunu sağlar. Bu shadow ağacı genel belgeden izole edilmiştir; harici stiller ve komut dosyaları bunu etkileyemez ve dahili stilleri ile komut dosyaları da dışarı sızmaz.

Örneğin, Shadow DOM kullanarak bir özel düğme bileşeni oluşturursanız, stilleri sayfadaki diğer nesneleri etkilemez. Benzer şekilde, aynı sınıf adına sahip öğeler çakışmaz.

Shadow DOM dışındaki normal HTML içeriğine Light DOM denir.

Shadow DOM'un Faydaları

  1. Kapsülleme

    • Shadow DOM, stil ve işlevselliği ayırarak, global stil ve betiklerle çakışmaları önler.
  2. Yeniden Kullanılabilirlik

    • Shadow DOM ile oluşturulan bileşenler, stil çakışmaları konusunda endişelenmeden farklı projelerde yeniden kullanılabilir.
  3. Bakım Kolaylığı

    • Kapsülleme, bileşenin mantığını ve stilini bağımsız hale getirir, bu da hata ayıklama ve bakımı kolaylaştırır.

Shadow DOM Oluşturmak

Shadow DOM kullanmak için bir HTML elemanına shadow root eklemeniz gerekir. İşte basit bir örnek:.

1// Select the host element
2const hostElement = document.querySelector('#shadow-host');
3
4// Attach a shadow root
5const shadowRoot = hostElement.attachShadow({ mode: 'open' });

Açıklama

Bu kod aşağıdaki öğeleri içerir:.

  1. Barındırıcı Öğesi

    • Shadow root'un bağlandığı normal bir DOM öğesi (bu örnekte, #shadow-host).
  2. Shadow Root

    • attachShadow kullanılarak oluşturulan shadow ağacının kökü.
  3. Mod

    • open modunda, harici JavaScript element.shadowRoot aracılığıyla shadow root'a erişebilir. Diğer yandan, kapalı (closed) mod erişime izin vermez.

Shadow DOM İçindeki Stil Tanımları

Shadow DOM kendi stil kapsama alanına sahiptir. Gölge ağacı içinde tanımlanan stiller yalnızca o ağaçtaki öğelere uygulanır. İşte bir örnek:.

1// Add content to the shadow root
2shadowRoot.innerHTML = `
3    <style>
4        p {
5            color: green;
6        }
7    </style>
8    <p>Scoped style inside Shadow DOM.</p>
9`;

Ana belgede çakışan stiller olsa bile, bunlar shadow tree içindeki paragrafı etkilemez.

1const content = document.getElementById('content');
2content.innerHTML = `
3    <style>
4        p {
5            color: red;
6        }
7    </style>
8    <p>This is in the main DOM.</p>
9`;
  • Shadow DOM içindeki paragraf yeşil kalır, dışarıdaki ise kırmızı olur.

Shadow DOM içindeki olaylar

Shadow DOM içindeki olaylar, düzenli DOM olaylarına benzer, ancak kapsülleme nedeniyle yayılma açısından farklı davranabilir.

İşte bir örnek:.

 1// Add an event listener inside Shadow DOM
 2shadowRoot.innerHTML = `
 3    <div id="button-container">
 4        <button id="shadow-button">Click Me</button>
 5    </div>
 6`;
 7
 8shadowRoot.querySelector('#shadow-button').addEventListener('click', (event) => {
 9    console.log('Button : Button clicked inside Shadow DOM');
10    console.log(event.target);
11});
12
13shadowRoot.querySelector('#button-container').addEventListener('click', (event) => {
14    console.log('Container : Button clicked inside Shadow DOM');
15    console.log(event.target);
16});
17
18hostElement.addEventListener('click', (event) => {
19    console.log('Event bubbled to the host element');
20    console.log(event.target);
21});
22
23document.addEventListener('click', (event) => {
24    console.log('Document listener');
25    console.log(event.target);
26});
  • Düğmeye tıklandığında her iki dinleyici de tetiklenir ve olay kabarcıklanmasının davranışı gösterilir.
  • Bir olay Shadow DOM içinde tetiklenip Light DOM'a ulaştığında, olayın targetı orijinal kaynağı yerine ana elemana yeniden yazılır.
    • Bu örnekte, Shadow DOM içinde event.target gerçek button öğesidir, ancak Shadow DOM dışında bu değer ana div elementiyle değiştirilir.

Shadow DOM ve Özel Öğeler

Shadow DOM ve özel öğeler, Web Components'ın ana bileşenleridir. Yeniden kullanılabilir ve kapsüllenmiş arayüz bileşenleri oluşturmak için kullanılan teknolojilerdir.

 1class MyCard extends HTMLElement {
 2    constructor() {
 3        super();
 4        const shadow = this.attachShadow({ mode: 'open' });
 5        shadow.innerHTML = `
 6        <style>
 7            p {
 8                color: blue;
 9            }
10        </style>
11        <p>I'm inside shadow DOM</p>
12        `;
13    }
14}
15
16customElements.define('my-card', MyCard);

Ana belge şu şekilde bir HTML içerir:.

1<my-card></my-card>
  • Özel öğeler içinde Shadow DOM kullanarak, stil çakışmalarına karşı dirençli, yeniden kullanılabilir bileşenler oluşturabilirsiniz. Bu kodda, my-card adında bir etiket oluşturulur ve MyCard sınıfıyla ilişkilendirilir. my-card içindeki <p> öğesi harici stillerden etkilenmez ve her zaman mavi olarak görüntülenir.

Slotlar: Light DOM İçeriğinin Dağıtılması

Slotlar, Light DOM içeriğini Shadow DOM içine yansıtmanıza olanak tanır. İşte bir örnek:.

 1class MyElement extends HTMLElement {
 2    constructor() {
 3        super();
 4        const shadow = this.attachShadow({ mode: 'open' });
 5
 6        shadow.innerHTML = `
 7        <style>
 8            .container {
 9                border: 2px solid #ccc;
10                padding: 16px;
11                border-radius: 8px;
12                font-family: sans-serif;
13            }
14            .header {
15                font-size: 1.2em;
16                color: darkblue;
17                margin-bottom: 8px;
18            }
19            .content {
20                font-size: 1em;
21                color: #333;
22            }
23        </style>
24        <div class="container">
25            <div class="header">
26                <slot name="header"></slot>
27            </div>
28            <div class="content">
29                <slot name="content"></slot>
30            </div>
31        </div>
32        `;
33    }
34}
35
36customElements.define('my-element', MyElement);

Ana belge şu şekilde bir HTML içerir:.

1<my-element>
2    <h3 slot="header">Header Content</h1>
3    <p slot="content">Main Content</p>
4</my-element>
  • Shadow DOM içindeki slot öğesi, ilgili slot özniteliğine sahip Light DOM içeriğini gösterir.

Sonuç

Shadow DOM, sağlam, yeniden kullanılabilir ve sürdürülebilir web bileşenleri oluşturmak için hayati bir araçtır. Stilleri ve işlevselliği kapsülleyerek uyuşmazlık olasılığını azaltır ve kod tabanı yönetimini basitleştirir.

Yukarıdaki makaleyi, YouTube kanalımızda Visual Studio Code'u kullanarak takip edebilirsiniz. Lütfen YouTube kanalını da kontrol edin.

YouTube Video