Shadow DOM ใน TypeScript
บทความนี้อธิบายเกี่ยวกับ Shadow DOM ใน TypeScript
เราจะอธิบายทุกอย่างอย่างละเอียดตั้งแต่พื้นฐานของ Shadow DOM
ไปจนถึงการใช้งานจริง พร้อมตัวอย่างโค้ดให้ทดลองใช้งานด้วย
YouTube Video
typescript-html-shadow-dom.html
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <title>TypeScript & 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>
90
91 <div class="container">
92 <h1>JavaScript Console</h1>
93 <button id="executeBtn">Execute</button>
94 <div id="output"></div>
95 </div>
96
97 <script>
98 // Override console.log to display messages in the #output element
99 (function () {
100 const originalLog = console.log;
101 console.log = function (...args) {
102 originalLog.apply(console, args);
103 const output = document.getElementById('output');
104 output.textContent += args.map(String).join(' ') + '\n';
105 };
106 })();
107
108 document.getElementById('executeBtn').addEventListener('click', () => {
109 // Prevent multiple loads
110 if (document.getElementById('externalScript')) return;
111
112 const script = document.createElement('script');
113 script.src = '/out/main.js';
114 script.id = 'externalScript';
115 //script.onload = () => console.log('typescript-html-shadow-dom.js loaded and executed.');
116 //script.onerror = () => console.log('Failed to load typescript-html-shadow-dom.js.');
117 document.body.appendChild(script);
118 });
119 </script>
120</body>
121</html>
คำอธิบายรายละเอียดและคำแนะนำเชิงปฏิบัติแบบทีละขั้นตอนเกี่ยวกับ Shadow DOM
Shadow DOM
เป็นหนึ่งในองค์ประกอบสำคัญของ Web Components มันสร้าง DOM tree ที่ถูกแยกออกมาโดยเฉพาะ ซึ่งช่วยแยกสไตล์และโครงสร้างของส่วนประกอบออกจากภายนอก ที่นี่ เราจะให้คำอธิบายเชิงลึกตั้งแต่พื้นฐานของ Shadow DOM
ไปจนถึงวิธีใช้งานในเชิงปฏิบัติ พร้อมตัวอย่างโค้ดให้ทดลองมือ
Shadow DOM
คืออะไร?
Shadow DOM
เป็นเทคโนโลยีมาตรฐานเว็บที่มีคุณสมบัติดังต่อไปนี้
-
การห่อหุ้ม (Encapsulation)
Shadow DOM
แยกโครงสร้าง DOM ภายในของส่วนประกอบออกจากภายนอก สไตล์และสคริปต์อื่น ๆ จะไม่ก้าวก่ายกัน ซึ่งช่วยให้การนำกลับมาใช้ซ้ำดีขึ้น -
เขตของสไตล์ที่เป็นอิสระ
สไตล์ภายใน
Shadow DOM
ไม่ส่งผลกระทบต่อ CSS ภายนอก ในทำนองเดียวกัน สไตล์ภายนอกจะไม่สามารถนำมาใช้ภายในShadow DOM
ได้ -
ต้นไม้ DOM ที่แยกขาดออกมา
Shadow DOM
ดำรงอยู่ในฐานะต้นไม้ที่แยกออกมาจาก DOM ปกติ และมีการจำกัดการเข้าถึงจาก DOM แม่
การใช้งานพื้นฐานของ Shadow DOM
โค้ดตัวอย่างต่อไปนี้เป็นตัวอย่างแรกที่ใช้ Shadow DOM
1class MyElement extends HTMLElement {
2 constructor() {
3 super();
4
5 // Attach Shadow DOM
6 const shadowRoot = this.attachShadow({ mode: 'open' });
7
8 // Add HTML and CSS inside Shadow DOM
9 shadowRoot.innerHTML = `
10 <style>
11 p {
12 color: blue;
13 font-size: 18px;
14 }
15 </style>
16 <p>This is inside Shadow DOM!</p>
17 `;
18 }
19}
20
21// Register the custom element
22customElements.define('my-element', MyElement);
23
24document.getElementById('content').innerHTML = `
25 <my-element></my-element>
26`;
- เบราว์เซอร์จะแสดงข้อความสีน้ำเงิน: 'นี่อยู่ภายใน Shadow DOM!' สไตล์ของข้อความนี้ไม่ได้รับผลกระทบจาก CSS ภายนอก
ขั้นตอนพื้นฐานของ Shadow DOM
ในการใช้ Shadow DOM
ตามตัวอย่างโค้ดนี้ คุณจะใช้เมธอด attachShadow
ในภาษา JavaScript ขั้นตอนพื้นฐานมีดังต่อไปนี้:
-
การสร้าง Custom Elements คัสตอมอีเลเมนต์คือแท็กที่คุณกำหนดเองได้เพิ่มเติมจากแท็ก HTML มาตรฐาน ในขั้นตอนนี้ คุณจะสร้างคลาสที่ขยายจาก
HTMLElement
เช่นคลาสMyElement
เพื่อให้เบราว์เซอร์รู้จักเป็นแท็กใหม่ โดยการลงทะเบียนคลาสที่สร้างไว้ด้วยcustomElements.define()
คุณจะสามารถใช้เป็นแท็กแบบคัสตอมใน HTML ได้ -
การผูก
Shadow DOM
ด้วยการเรียกthis.attachShadow()
ภายในคัสตอมอีเลเมนต์ คุณจะสามารถสร้างShadow DOM
ได้ -
การเพิ่ม HTML และ CSS ภายใน
Shadow DOM
ภายในShadow DOM
คุณสามารถกำหนดโครงสร้าง HTML และรูปแบบสไตล์ของตนเองได้ ตัวอย่างเช่น การกำหนด HTML และ CSS ลงในinnerHTML
จะทำให้มีรูปร่างและพฤติกรรมที่เป็นอิสระ ไม่ถูกรบกวนโดย CSS หรือ HTML จากภายนอก ซึ่งจะช่วยให้คุณสร้างคอมโพเนนต์ที่เป็นเอกเทศ
โหมดของ Shadow DOM
: open
และ closed
Shadow DOM
มีสองโหมด: open
และ closed
- โหมด Open: สามารถเข้าถึง
shadowRoot
ที่แนบอยู่กับShadow DOM
จากภายนอกได้ - โหมด Closed: ไม่สามารถเข้าถึง
shadowRoot
ที่แนบอยู่กับShadow DOM
จากภายนอกได้
ด้านล่างเป็นโค้ดตัวอย่างที่แสดงความแตกต่างระหว่างสองโหมด
1class OpenElement extends HTMLElement {
2 constructor() {
3 super();
4 this.attachShadow({ mode: 'open' }).innerHTML = `
5 <p>Open Shadow DOM</p>
6 `;
7 }
8}
9
10class ClosedElement extends HTMLElement {
11 constructor() {
12 super();
13 this.attachShadow({ mode: 'closed' }).innerHTML = `
14 <p>Closed Shadow DOM</p>
15 `;
16 }
17}
18
19customElements.define('open-element', OpenElement);
20customElements.define('closed-element', ClosedElement);
21
22document.getElementById('content').innerHTML = `
23 <open-element></open-element>
24 <closed-element></closed-element>
25`;
26
27const openElement = document.querySelector('open-element') as OpenElement;
28console.log(openElement.shadowRoot); // ShadowRootが出力される
29
30const closedElement = document.querySelector('closed-element') as ClosedElement;
31console.log(closedElement.shadowRoot); // nullが出力される
- การเลือกโหมด
closed
จะทำให้ไม่สามารถเข้าถึงคุณสมบัติshadowRoot
ได้
การห่อหุ้มสไตล์โดยใช้ Shadow DOM
ด้วยการใช้ Shadow DOM
คุณสามารถห่อหุ้มสไตล์ในคอมโพเนนต์ของคุณอย่างสมบูรณ์
ตัวอย่างต่อไปนี้แสดงการแยกของสไตล์ระดับโลกและสไตล์ภายใน Shadow DOM
1class StyledElement extends HTMLElement {
2 constructor() {
3 super();
4 const shadowRoot = this.attachShadow({ mode: 'open' });
5
6 shadowRoot.innerHTML = `
7 <style>
8 p {
9 background-color: lightblue;
10 padding: 10px;
11 border: 1px solid blue;
12 }
13 </style>
14 <p>Shadow DOM Styled Content</p>
15 `;
16 }
17}
18
19customElements.define('styled-element', StyledElement);
20
21document.getElementById('content').innerHTML = `
22 <style>
23 p {
24 color: red;
25 font-weight: bold;
26 }
27 </style>
28
29 <styled-element></styled-element>
30`;
- องค์ประกอบ
p
ที่อยู่ภายในShadow DOM
จะไม่ได้รับผลกระทบจากสไตล์แบบทั่วโลก และจะมีสไตล์เฉพาะตัวของตนเองถูกนำมาใช้
ตัวอย่างการใช้งาน Shadow DOM
: เครื่องมือคำแนะนำที่กำหนดเอง
ต่อไปเราจะแนะนำตัวอย่างการสร้างเครื่องมือคำแนะนำที่กำหนดเองโดยใช้ Shadow DOM
1class Tooltip extends HTMLElement {
2 constructor() {
3 super();
4
5 const shadowRoot = this.attachShadow({ mode: 'open' });
6
7 shadowRoot.innerHTML = `
8 <style>
9 :host {
10 position: relative;
11 display: inline-block;
12 cursor: pointer;
13 }
14
15 .tooltip {
16 visibility: hidden;
17 background-color: black;
18 color: white;
19 text-align: center;
20 padding: 5px;
21 border-radius: 5px;
22 position: absolute;
23 bottom: 125%;
24 left: 50%;
25 transform: translateX(-50%);
26 white-space: nowrap;
27 }
28
29 :host(:hover) .tooltip {
30 visibility: visible;
31 }
32 </style>
33 <slot></slot>
34 <div class="tooltip">Tooltip text</div>
35 `;
36 }
37}
38
39customElements.define('custom-tooltip', Tooltip);
40
41document.getElementById('content').innerHTML = `
42 <custom-tooltip>
43 Hover over me
44 <span slot="tooltip">This is a custom tooltip!</span>
45 </custom-tooltip>
46`;
- โค้ดนี้สร้างเครื่องมือคำแนะนำที่กำหนดเองและแสดงเครื่องมือคำแนะนำที่มีสไตล์เมื่อมีการเลื่อนเมาส์
สรุป
Shadow DOM
เป็นเทคโนโลยีที่สำคัญสำหรับ Web Components ที่มอบ DOM และขอบเขตสไตล์ที่ถูกห่อหุ้ม ที่นี่เราได้ครอบคลุมพื้นฐานของ Shadow DOM
การใช้งาน ความแตกต่างของโหมด การห่อหุ้มสไตล์ และตัวอย่างการใช้งานจริง ด้วยการใช้ประโยชน์จากคุณสมบัติเหล่านี้ คุณจะสามารถสร้างคอมโพเนนต์ที่นำกลับมาใช้ได้และแข็งแกร่ง
คุณสามารถติดตามบทความข้างต้นโดยใช้ Visual Studio Code บนช่อง YouTube ของเรา กรุณาตรวจสอบช่อง YouTube ด้วย