Web
น้องๆ เคยเจอปัญหาเขียนโค้ด HTML ซ้ำๆ กันไหม? เช่น ปุ่มสวยๆ ที่ต้องใช้หลายหน้า หรือกล่องข้อความพิเศษที่หน้าตาเหมือนกันเป๊ะๆ ทุกที่ สมัยผมทำร้านเน็ต SiamCafe.net ยุคแรกๆ นะ (ตั้งแต่ปี 97) โค้ด HTML นี่รกมาก เพราะต้องก็อปวางๆ แก้ๆ วนไป
Custom Elements เนี่ยแหละ พระเอกขี่ม้าขาว! มันคือการสร้าง tag HTML ของตัวเองขึ้นมาเลย! คิดซะว่าเราสร้าง element ใหม่ๆ ให้ browser รู้จัก เหมือนเราสอนภาษาใหม่ให้มันนั่นแหละ พอสร้างแล้วก็เอาไปใช้ซ้ำๆ ได้ง่ายมาก แก้ทีเดียวก็เปลี่ยนหมดทุกที่ ประหยัดเวลาไปเยอะเลย
สำคัญยังไงน่ะเหรอ? ลองนึกภาพว่าเรามี Lego แล้วเราสร้างชิ้นส่วนพิเศษขึ้นมาเองได้ เอาไปต่อกับ Lego ชิ้นอื่นได้หมด โค้ดเราก็จะ modular ขึ้น อ่านง่ายขึ้น maintain ง่ายขึ้น แถมยังเอาไปใช้กับ framework อะไรก็ได้ React, Angular, Vue.js ได้หมด เพราะมันคือ HTML ธรรมดาๆ ที่ browser เข้าใจ
ก่อนจะไปลุยโค้ดกัน น้องๆ ต้องเข้าใจพื้นฐาน HTML, CSS, และ JavaScript ก่อนนะ ถ้ายังไม่แม่น ลองไปทบทวนดูก่อน SiamCafe Blog มีบทความพื้นฐานเยอะแยะเลย
HTML คือกระดูกของเว็บเรา มันคือโครงสร้างหลักที่เราจะเอา Custom Elements ไปใส่ เช่น
<my-button>คลิกเลย!</my-button>
JavaScript คือตัวควบคุมการทำงานของเว็บเรา เราจะใช้ JavaScript สร้าง Custom Elements กำหนด logic และจัดการ event ต่างๆ
class MyButton extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `<button><slot></slot></button>`;
}
}
customElements.define('my-button', MyButton);
CSS คือตัวตกแต่งเว็บเรา เราจะใช้ CSS กำหนดหน้าตาของ Custom Elements ให้สวยงามตามที่เราต้องการ
my-button button {
background-color: lightblue;
padding: 10px 20px;
border: none;
cursor: pointer;
}
เอาล่ะ! มาเริ่มสร้าง Custom Elements กันเลยดีกว่า ผมจะยกตัวอย่างง่ายๆ ให้เห็นภาพนะ
ขั้นแรก เราต้องสร้าง class ที่สืบทอดมาจาก HTMLElement ซึ่งเป็น class หลักของ HTML elements ทั้งหมด
class MyElement extends HTMLElement {
constructor() {
super();
// โค้ด initialization อยู่ตรงนี้
}
}
constructor() คือส่วนที่ทำงานตอนที่เราสร้าง element นี้ขึ้นมาใหม่
Shadow DOM คือ DOM ที่ซ่อนอยู่ภายใน Custom Element ของเรา มันช่วยให้ CSS และ JavaScript ของ Custom Element ไม่ไปกระทบกับส่วนอื่นๆ ของเว็บ
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' }); // สร้าง Shadow DOM
this.shadowRoot.innerHTML = `<p>Hello from MyElement!</p>`; // ใส่ HTML เข้าไป
}
}
attachShadow({ mode: 'open' }) สร้าง Shadow DOM แบบ "open" ซึ่งหมายความว่าเราสามารถเข้าถึง Shadow DOM จาก JavaScript ภายนอกได้ (ถ้าใช้ mode: 'closed' จะเข้าถึงไม่ได้)
customElements.define()สุดท้าย เราต้องบอก browser ว่า class MyElement ของเรา คือ Custom Element ที่ชื่ออะไร
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `<p>Hello from MyElement!</p>`;
}
}
customElements.define('my-element', MyElement); // กำหนดชื่อ
customElements.define('my-element', MyElement) บอก browser ว่า tag <my-element> จะใช้ class MyElement ในการสร้าง
ทีนี้เราก็เอา Custom Element ของเราไปใช้ใน HTML ได้เลย
<my-element></my-element>
ง่ายไหมล่ะ? แค่นี้เราก็มี Custom Element ของตัวเองแล้ว!
Custom Elements มี lifecycle callbacks ที่เราสามารถใช้จัดการเหตุการณ์ต่างๆ ในช่วงชีวิตของ element ได้ เช่น
connectedCallback(): เรียกเมื่อ element ถูกเพิ่มเข้าไปใน DOMdisconnectedCallback(): เรียกเมื่อ element ถูกเอาออกจาก DOMattributeChangedCallback(name, oldValue, newValue): เรียกเมื่อ attribute ของ element เปลี่ยนแปลงadoptedCallback(): เรียกเมื่อ element ถูกย้ายไปอยู่ใน document ใหม่ลองเอาไปประยุกต์ใช้ดูนะ มันมีประโยชน์มากๆ ในการจัดการ state และ event ต่างๆ
แน่นอนว่า Custom Elements ไม่ใช่ทางเลือกเดียวในการสร้าง component ที่ใช้ซ้ำได้ แต่ผมว่ามันเป็นทางเลือกที่ดีที่สุดทางหนึ่งนะ ลองมาดูตารางเปรียบเทียบกัน
| Feature | Web Components (Custom Elements) | Framework Components (React, Angular, Vue) |
|---|---|---|
| Dependency | None (Native browser feature) | Requires a specific framework |
| Reusability | Highly reusable across different frameworks | Limited to the specific framework |
| Performance | Generally good performance | Performance can vary depending on the framework |
| Learning Curve | Relatively low learning curve | Learning curve can be higher depending on the framework |
| SEO | SEO friendly | SEO can be challenging depending on the framework |
จากตารางจะเห็นว่า Custom Elements มีข้อดีตรงที่เป็น native browser feature ไม่ต้องพึ่ง framework อะไรเลย แถมยังเอาไปใช้ซ้ำได้กับทุก framework อีกด้วย แต่ถ้าใครถนัด framework อยู่แล้ว ก็ไม่จำเป็นต้องเปลี่ยนมาใช้ Custom Elements ก็ได้นะ เลือกใช้สิ่งที่เหมาะกับโปรเจกต์ของเราที่สุด
สุดท้ายนี้ อยากฝากน้องๆ ว่า Custom Elements เป็นเครื่องมือที่ทรงพลังมากๆ ลองเอาไปศึกษาและประยุกต์ใช้กันดู SiamCafe Blog จะคอยอัพเดทบทความดีๆ เกี่ยวกับ Web Development ให้เรื่อยๆ นะครับ
ดูวิดีโอเพิ่มเติมเกี่ยวกับWeb Components Custom Elements:
เอาล่ะน้องๆ มาถึงส่วนที่พี่จะแชร์เคล็ดลับจากประสบการณ์จริง สมัยผมทำร้านเน็ต SiamCafe.net เนี่ย เรื่อง Web Components ยังไม่มีหรอก แต่คอนเซ็ปต์ของการทำอะไรที่เป็นโมดูลาร์, reusable มันมีมานานแล้ว
ลองคิดดูดิ สมัยก่อนจะทำเว็บแต่ละที ต้อง copy paste code กันให้วุ่นวาย ยิ่งเว็บร้านเกมส์นี่ หน้าตาต้องหวือหวา animation เพียบ ถ้าไม่ได้ component ดีๆ นี่ตายเลย
Web Components มันคือ solution ที่ทำให้ชีวิตเราง่ายขึ้นเยอะมากๆ แต่ก็ต้องใช้ให้ถูกวิธีนะ
เรื่อง scope ของ CSS นี่สำคัญสุดๆ ไม่งั้น component เราไปตีกับชาวบ้านเค้าหมด สมัยก่อนใช้ iframe ช่วย แต่ Web Components เค้ามี Shadow DOM นี่แหละ คือพระเอกตัวจริง
จำไว้เลยว่า CSS ที่อยู่ใน Shadow DOM จะไม่ leak ออกไปข้างนอก และ CSS ข้างนอกก็เข้ามาใน Shadow DOM ไม่ได้ (ยกเว้นใช้ CSS Variables)
<!-- ใน Custom Element -->
<style>
p { color: blue; }
</style>
<p>This is a paragraph inside the component.</p>
<!-- ใน HTML หลัก -->
<style>
p { color: red; }
</style>
<p>This is a paragraph outside the component.</p>
paragraph ใน component จะเป็นสีฟ้า ส่วนข้างนอกจะเป็นสีแดง ถึงแม้เราจะ define p selector ทั้งคู่ก็ตาม
Component เรามันก็เหมือนกล่องดำ ถ้ามันทำงานเสร็จ หรือมีอะไรเกิดขึ้นข้างใน เราต้องบอกให้ข้างนอกรู้ด้วย Custom Events นี่แหละ คือวิธีที่ถูกต้อง
สมัยก่อนผมใช้ callback function บ้าง, global variable บ้าง มั่วไปหมด สรุปคือแก้กันวุ่นวาย Custom Events นี่แหละ ช่วยชีวิต
// ใน Custom Element
this.dispatchEvent(new CustomEvent('my-event', { detail: { message: 'Hello from the component!' } }));
// ใน HTML หลัก
document.querySelector('my-component').addEventListener('my-event', function(event) {
console.log(event.detail.message); // Output: Hello from the component!
});
ง่ายๆ แค่นี้เอง Component ก็สื่อสารกับโลกภายนอกได้แล้ว
Properties กับ Attributes มันดูเหมือนกัน แต่จริงๆ แล้วไม่เหมือนกันนะน้อง Properties มันคือ JavaScript properties ส่วน Attributes มันคือ HTML attributes
ถ้าเราอยากให้ component เรา responsive ต่อการเปลี่ยนแปลงของ attribute เราต้องใช้ `attributeChangedCallback`
static get observedAttributes() { return ['my-attribute']; }
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'my-attribute') {
// ทำอะไรบางอย่างเมื่อ attribute เปลี่ยน
this.myProperty = newValue; //อัพเดท property จาก attribute
}
}
จำไว้ว่า Attribute คือ Initial State ส่วน Property คือ Current State
สมัยก่อนผมติด inheritance มาก ทำอะไรก็ extends class อย่างเดียว ปวดหัวสุดๆ Component Composition นี่แหละ คือทางออก
แทนที่จะ extends class เราเอา component เล็กๆ มาประกอบกันเป็น component ใหญ่ มันจะ flexible กว่าเยอะ
ลองคิดดูดิ component ที่แสดง product detail อาจจะประกอบด้วย component ที่แสดง image, component ที่แสดง price, component ที่แสดง description อะไรแบบนี้
ทำได้แน่นอน! Google bot มัน render JavaScript ได้แล้ว แต่ก็ต้องทำให้ถูกต้องนะ Make sure component เรา render content ที่สำคัญๆ ได้ตั้งแต่ initial load
Browser สมัยใหม่ support หมดแล้ว แต่ถ้าต้อง support browser เก่าๆ ก็ต้องใช้ polyfills ช่วยนะ
LitElement, Stencil, Polymer พวกนี้เป็นตัวเลือกที่ดี แต่สุดท้ายก็ขึ้นอยู่กับความชอบ และ requirement ของโปรเจกต์
Custom Elements มันเป็น Web Standard ส่วน React/Vue/Angular มันคือ frameworks/libraries Custom Elements มัน low-level กว่า แต่ก็เอาไปใช้ร่วมกับ frameworks เหล่านี้ได้
Web Components มันคืออนาคตของการพัฒนาเว็บ! มันทำให้เราสร้าง component ที่ reusable, encapsulated, และ platform-independent ได้
ถึงมันจะดูยากในช่วงแรก แต่ถ้าเข้าใจ concept แล้ว จะพบว่ามันช่วยให้ชีวิตเราง่ายขึ้นเยอะมากๆ ลองเอาไปปรับใช้กันดูนะน้องๆ แล้วจะติดใจ
อย่าลืมแวะไปอ่านบทความอื่นๆ ที่ SiamCafe Blog นะ มีอะไรดีๆ อีกเยอะเลย
สนใจเรื่อง Forex แวะไปดูได้ที่ iCafeForex