Tất cả chúng ta đều có những dự án mà chúng ta không muốn thực hiện. Mã đã trở nên không thể quản lý được, phạm vi đã phát triển, các bản sửa lỗi nhanh được áp dụng trên các bản sửa lỗi khác và cấu trúc bị thu gọn dưới sức nặng của mã spaghetti. Mã hóa có thể là một công việc kinh doanh lộn xộn.
Các dự án được hưởng lợi từ việc sử dụng các mô-đun đơn giản, độc lập có một trách nhiệm duy nhất. Mã mô-đun được đóng gói, vì vậy không cần phải lo lắng về việc triển khai. Miễn là bạn biết mô-đun sẽ xuất gì khi được cung cấp một tập hợp đầu vào, bạn không nhất thiết phải hiểu cách nó đạt được mục tiêu đó.
Việc áp dụng các khái niệm mô-đun cho một ngôn ngữ lập trình duy nhất là đơn giản, nhưng việc phát triển web đòi hỏi sự kết hợp đa dạng của các công nghệ. Các trình duyệt phân tích cú pháp HTML, CSS và JavaScript để hiển thị nội dung, kiểu và chức năng của trang.
Không phải lúc nào chúng cũng kết hợp dễ dàng bởi vì:
- Mã liên quan có thể được chia thành ba hoặc nhiều tệp, và
- Các kiểu toàn cục và các đối tượng JavaScript có thể can thiệp vào nhau theo những cách không mong muốn.
Những vấn đề này ngoài những vấn đề gặp phải bởi thời gian chạy ngôn ngữ, khuôn khổ, cơ sở dữ liệu và các phần phụ thuộc khác được sử dụng trên máy chủ.
Xem hướng dẫn bằng video của chúng tôi về các thành phần web
Thành phần Web là gì?
Thành phần Web là một cách để tạo một khối mã đơn trách nhiệm được đóng gói, có thể được sử dụng lại trên bất kỳ trang nào.
Xem xét thẻ HTML <video>
. Với một URL, người xem có thể sử dụng các điều khiển như phát, tạm dừng, lùi lại, tiến và điều chỉnh âm lượng.
Tạo kiểu và chức năng được cung cấp, mặc dù bạn có thể thực hiện sửa đổi bằng cách sử dụng các thuộc tính khác nhau và lệnh gọi API JavaScript. Bất kỳ số lượng phần tử <video>
nào cũng có thể được đặt bên trong các thẻ khác và chúng sẽ không xung đột.
Điều gì xảy ra nếu bạn yêu cầu chức năng tùy chỉnh của riêng mình? Ví dụ, một phần tử hiển thị số lượng từ trên trang? Không có thẻ HTML <wordcount>
(chưa).
Các khung công tác như React và Vue.js cho phép các nhà phát triển tạo các thành phần web trong đó nội dung, kiểu dáng và chức năng có thể được xác định trong một tệp JavaScript duy nhất. Chúng giải quyết nhiều vấn đề lập trình phức tạp nhưng hãy nhớ rằng:
- Bạn phải học cách sử dụng khuôn khổ đó và cập nhật mã của mình khi nó phát triển.
- Một thành phần được viết cho một khuôn khổ này hiếm khi tương thích với một khuôn khổ khác.
- Các khuôn khổ ngày càng phổ biến và suy yếu. Bạn sẽ trở nên phụ thuộc vào những ý tưởng bất chợt và ưu tiên của nhóm phát triển và người dùng.
- Cấu phần Web tiêu chuẩn có thể thêm chức năng của trình duyệt, điều này rất khó đạt được chỉ trong JavaScript (chẳng hạn như Shadow DOM).
May mắn thay, các khái niệm phổ biến được giới thiệu trong các thư viện và khuôn khổ thường đi vào các tiêu chuẩn web. Phải mất một thời gian, nhưng Thành phần Web đã đến.
Sơ lược về lịch sử các thành phần web
Sau nhiều lần khởi đầu sai theo nhà cung cấp, khái niệm Thành phần Web tiêu chuẩn được Alex Russell giới thiệu lần đầu tiên tại Hội nghị Fronteers vào năm 2011. Thư viện Polymer của Google (một polyfill dựa trên các đề xuất hiện tại) đến hai năm sau đó, nhưng các triển khai ban đầu đã không xuất hiện trong Chrome và Safari cho đến năm 2016.
Các nhà cung cấp trình duyệt đã mất thời gian để thương lượng chi tiết, nhưng Thành phần Web đã được thêm vào Firefox vào năm 2018 và Edge vào năm 2020 (khi Microsoft chuyển sang công cụ Chromium).
Có thể hiểu rằng, rất ít nhà phát triển sẵn sàng hoặc có thể áp dụng Thành phần Web, nhưng cuối cùng chúng tôi đã đạt được mức độ hỗ trợ trình duyệt tốt với các API ổn định. Không phải mọi thứ đều hoàn hảo, nhưng chúng là một sự thay thế ngày càng khả thi cho các thành phần dựa trên khuôn khổ.
Ngay cả khi bạn chưa sẵn sàng loại bỏ yêu thích của mình, Thành phần Web tương thích với mọi khuôn khổ và các API sẽ được hỗ trợ trong nhiều năm tới.
Kho lưu trữ Thành phần Web được tạo sẵn có sẵn cho mọi người xem:
- WebComponents.org
- Thư viện thành phần
- thành phần chung
- thành phần web-ví dụ
- tuyệt vời-độc lập
- thành phần có thể truy cập
- Giao diện người dùng Kickstand
… Nhưng viết mã của riêng bạn thì thú vị hơn!
Hướng dẫn này cung cấp giới thiệu đầy đủ về các Thành phần Web được viết mà không có khung JavaScript. Bạn sẽ tìm hiểu chúng là gì và làm thế nào để điều chỉnh chúng cho các dự án web của bạn. Bạn sẽ cần một số kiến thức về HTML5, CSS và JavaScript.
Bắt đầu với các thành phần Web
Thành phần Web là các phần tử HTML tùy chỉnh như <hello-world></hello-world>
. Tên phải chứa một dấu gạch ngang để không bao giờ đụng độ với các phần tử được hỗ trợ chính thức trong đặc tả HTML.
Bạn phải xác định một lớp ES2015 để kiểm soát phần tử. Nó có thể được đặt tên bất cứ thứ gì, nhưng HelloWorld là một thực tế phổ biến. Nó phải mở rộng giao diện HTMLElement, giao diện này đại diện cho các thuộc tính và phương thức mặc định của mọi phần tử HTML.
Lưu ý: Firefox cho phép bạn mở rộng các phần tử HTML cụ thể như HTMLParagraphElement, HTMLImageElement hoặc HTMLButtonElement. Điều này không được hỗ trợ trong các trình duyệt khác và không cho phép bạn tạo Shadow DOM.
Để làm bất cứ điều gì hữu ích, lớp này yêu cầu một phương thức có tên là connectCallback () được gọi khi phần tử được thêm vào tài liệu:
class HelloWorld extends HTMLElement { // connect component connectedCallback() { this.textContent = 'Hello World!'; } }
Trong ví dụ này, văn bản của phần tử được đặt thành “Hello World”.
Lớp phải được đăng ký với CustomElementRegistry để xác định nó như một trình xử lý cho một phần tử cụ thể:
customElements.define( 'hello-world', HelloWorld );
Trình duyệt hiện liên kết phần tử <hello-world>
với lớp HelloWorld của bạn khi JavaScript của bạn được tải (ví dụ: <script type="module" src="./helloworld.js"></script>
).
Bây giờ bạn có một phần tử tùy chỉnh!
Trình diễn CodePen
Thành phần này có thể được tạo kiểu trong CSS giống như bất kỳ phần tử nào khác:
hello-world { font-weight: bold; color: red; }
Thêm thuộc tính
Thành phần này không có lợi vì cùng một văn bản được xuất ra. Giống như bất kỳ phần tử nào khác, chúng tôi có thể thêm các thuộc tính HTML:
<hello-world name="Craig"></hello-world>
Điều này có thể ghi đè văn bản thành “Xin chào Craig!” được hiển thị. Để đạt được điều này, bạn có thể thêm một hàm constructor () vào lớp HelloWorld , được chạy khi mỗi đối tượng được tạo. Nó phải:
- gọi phương thức super () để khởi tạo HTMLElement mẹ và
- thực hiện các khởi tạo khác. Trong trường hợp này, chúng tôi sẽ xác định thuộc tính tên được đặt thành mặc định là “Thế giới”:
class HelloWorld extends HTMLElement { constructor() { super(); this.name = 'World'; } // more code...
Thành phần của bạn chỉ quan tâm đến thuộc tính tên . Thuộc tính static secureAttributes () sẽ trả về một mảng thuộc tính để quan sát:
// component attributes static get observedAttributes() { return ['name']; }
Phương thức thuộc tính propertyChangedCallback () được gọi khi một thuộc tính được xác định trong HTML hoặc được thay đổi bằng JavaScript. Nó đã chuyển tên thuộc tính, giá trị cũ và giá trị mới:
// attribute change attributeChangedCallback(property, oldValue, newValue) { if (oldValue === newValue) return; this[ property ] = newValue; }
Trong ví dụ này, chỉ thuộc tính name sẽ được cập nhật, nhưng bạn có thể thêm các thuộc tính bổ sung nếu cần.
Cuối cùng, bạn cần chỉnh sửa thông báo trong phương thức connectCallback () :
// connect component connectedCallback() { this.textContent = `Hello ${ this.name }!`; }
Trình diễn CodePen
Phương pháp vòng đời
Trình duyệt tự động gọi sáu phương thức trong suốt vòng đời của trạng thái Thành phần Web. Danh sách đầy đủ được cung cấp ở đây, mặc dù bạn đã thấy bốn danh sách đầu tiên trong các ví dụ ở trên:
người xây dựng()
Nó được gọi khi thành phần được khởi tạo lần đầu tiên. Nó phải gọi super () và có thể đặt bất kỳ giá trị mặc định nào hoặc thực hiện các quy trình kết xuất trước khác.
static quan sátAttributes ()
Trả về một mảng thuộc tính mà trình duyệt sẽ quan sát.
thuộc tínhChangedCallback (propertyName, oldValue, newValue)
Được gọi bất cứ khi nào một thuộc tính quan sát được thay đổi. Những định nghĩa trong HTML được chuyển ngay lập tức, nhưng JavaScript có thể sửa đổi chúng:
document.querySelector('hello-world').setAttribute('name', 'Everyone');
Phương thức có thể cần kích hoạt kết xuất lại khi điều này xảy ra.
kết nốiCallback ()
Chức năng này được gọi khi Thành phần Web được nối vào Mô hình Đối tượng Tài liệu. Nó sẽ chạy bất kỳ kết xuất cần thiết nào.
đã ngắt kết nốiCallback ()
Nó được gọi khi Thành phần Web bị loại bỏ khỏi Mô hình Đối tượng Tài liệu. Điều này có thể hữu ích nếu bạn cần dọn dẹp, chẳng hạn như xóa trạng thái đã lưu trữ hoặc hủy bỏ các yêu cầu Ajax.
thông quaCallback ()
Hàm này được gọi khi một Thành phần Web được chuyển từ tài liệu này sang tài liệu khác. Bạn có thể tìm thấy một cách sử dụng cho điều này, mặc dù tôi đã cố gắng nghĩ ra bất kỳ trường hợp nào!
Cách các thành phần web tương tác với các thành phần khác
Thành phần Web cung cấp một số chức năng độc đáo mà bạn sẽ không tìm thấy trong các khung JavaScript.
DOM bóng
Mặc dù Thành phần Web mà chúng tôi đã xây dựng ở trên hoạt động, nhưng nó không miễn nhiễm với sự can thiệp từ bên ngoài và CSS hoặc JavaScript có thể sửa đổi nó. Tương tự, các kiểu bạn xác định cho thành phần của mình có thể bị rò rỉ và ảnh hưởng đến những người khác.
Shadow DOM giải quyết vấn đề đóng gói này bằng cách gắn một DOM riêng biệt vào Thành phần Web với:
const shadow = this.attachShadow({ mode: 'closed' });
Chế độ có thể là:
Đăng kí để nhận thư mới
- “Mở” – JavaScript ở trang ngoài có thể truy cập Shadow DOM (sử dụng Element.shadowRoot) hoặc
- “Đã đóng” – Shadow DOM chỉ có thể được truy cập trong Thành phần Web.
Shadow DOM có thể được thao tác giống như bất kỳ phần tử DOM nào khác:
connectedCallback() { const shadow = this.attachShadow({ mode: 'closed' }); shadow.innerHTML = ` <style> p { text-align: center; font-weight: normal; padding: 1em; margin: 0 0 2em 0; background-color: #eee; border: 1px solid #666; } </style> <p>Hello ${ this.name }!</p>`; }
Bây giờ thành phần hiển thị văn bản “Xin chào” bên trong một phần tử <p>
và tạo kiểu cho nó. Nó không thể được sửa đổi bởi JavaScript hoặc CSS bên ngoài thành phần, mặc dù một số kiểu như phông chữ và màu sắc được kế thừa từ trang vì chúng không được xác định rõ ràng.
Trình diễn CodePen
Các kiểu trong phạm vi Thành phần Web này không thể ảnh hưởng đến các đoạn khác trên trang hoặc thậm chí các thành phần <hello-world>
khác.
Lưu ý rằng bộ chọn CSS :host
có thể tạo kiểu cho phần tử <hello-world>
bên ngoài từ bên trong Thành phần Web:
:host { transform: rotate(180deg); }
Bạn cũng có thể đặt các kiểu được áp dụng khi phần tử sử dụng một lớp cụ thể, ví dụ: <hello-world class="rotate90">
:
:host(.rotate90) { transform: rotate(90deg); }
Mẫu HTML
Việc xác định HTML bên trong tập lệnh có thể trở nên không thực tế đối với các Thành phần Web phức tạp hơn. Mẫu cho phép bạn xác định một đoạn HTML trong trang của bạn mà Thành phần Web của bạn có thể sử dụng. Điều này có một số lợi ích:
- Bạn có thể chỉnh sửa mã HTML mà không cần phải viết lại các chuỗi bên trong JavaScript của mình.
- Các thành phần có thể được tùy chỉnh mà không cần phải tạo các lớp JavaScript riêng biệt cho từng loại.
- Định nghĩa HTML trong HTML dễ dàng hơn – và nó có thể được sửa đổi trên máy chủ hoặc máy khách trước khi thành phần hiển thị.
Các mẫu được định nghĩa trong <template>
và việc gán một ID để bạn có thể tham chiếu nó trong lớp thành phần là rất thực tế. Ví dụ này ba đoạn văn để hiển thị thông báo “Xin chào”:
<template id="hello-world"> <style> p { text-align: center; font-weight: normal; padding: 0.5em; margin: 1px 0; background-color: #eee; border: 1px solid #666; } </style> <p class="hw-text"></p> <p class="hw-text"></p> <p class="hw-text"></p> </template>
Lớp Thành phần Web có thể truy cập vào mẫu này, lấy nội dung của nó và sao chép các phần tử để đảm bảo bạn đang tạo một phân đoạn DOM duy nhất ở mọi nơi mà nó được sử dụng:
const template = document.getElementById('hello-world').content.cloneNode(true);
DOM có thể được sửa đổi và thêm trực tiếp vào Shadow DOM:
connectedCallback() { const shadow = this.attachShadow({ mode: 'closed' }), template = document.getElementById('hello-world').content.cloneNode(true), hwMsg = `Hello ${ this.name }`; Array.from( template.querySelectorAll('.hw-text') ) .forEach( n => n.textContent = hwMsg ); shadow.append( template ); }
Trình diễn CodePen
Các khe mẫu
Các khe cho phép bạn tùy chỉnh một mẫu. Giả sử bạn muốn sử dụng Thành phần Web <hello-world>
của mình nhưng đặt thông báo trong tiêu đề <h1> trong Shadow DOM. Bạn có thể viết mã này:
<hello-world name="Craig"> <h1 slot="msgtext">Hello Default!</h1> </hello-world>
(Lưu ý thuộc tính vị trí .)
Bạn có thể tùy ý muốn thêm các phần tử khác, chẳng hạn như một đoạn văn khác:
<hello-world name="Craig"> <h1 slot="msgtext">Hello Default!</h1> <p>This text will become part of the component.</p> </hello-world>
Các khe giờ có thể được triển khai trong mẫu của bạn:
Cần một giải pháp lưu trữ mang lại cho bạn lợi thế cạnh tranh? Kinsta giúp bạn bao phủ bởi tốc độ đáng kinh ngạc, bảo mật hiện đại và tự động mở rộng quy mô. Kiểm tra các kế hoạch của chúng tôi
<template id="hello-world"> <slot name="msgtext" class="hw-text"></slot> <slot></slot> </template>
Thuộc tính vị trí phần tử được đặt thành “msgtext” ( <h1>
) được chèn tại điểm có một <slot>
có tên là “msgtext.” <p>
không được gán tên vùng, nhưng nó được sử dụng trong <slot>
có sẵn tiếp theo chưa được đặt tên. Trên thực tế, mẫu sẽ trở thành:
<template id="hello-world"> <slot name="msgtext" class="hw-text"> <h1 slot="msgtext">Hello Default!</h1> </slot> <slot> <p>This text will become part of the component.</p> </slot> </template>
Nó không hoàn toàn đơn giản trong thực tế. Phần tử <slot>
trong Shadow DOM trỏ đến các phần tử được chèn. Bạn chỉ có thể truy cập chúng bằng cách định vị một <slot>
sau đó sử dụng phương thức .assignedNodes () để trả về một mảng con bên trong. Phương thức connectCallback () được cập nhật:
connectedCallback() { const shadow = this.attachShadow({ mode: 'closed' }), hwMsg = `Hello ${ this.name }`; // append shadow DOM shadow.append( document.getElementById('hello-world').content.cloneNode(true) ); // find all slots with a hw-text class Array.from( shadow.querySelectorAll('slot.hw-text') ) // update first assignedNode in slot .forEach( n => n.assignedNodes()[0].textContent = hwMsg ); }
Trình diễn CodePen
Ngoài ra, bạn không thể tạo kiểu trực tiếp cho các phần tử được chèn, mặc dù bạn có thể nhắm mục tiêu các vị trí cụ thể trong Thành phần Web của mình:
<template id="hello-world"> <style> slot[name="msgtext"] { color: green; } </style> <slot name="msgtext" class="hw-text"></slot> <slot></slot> </template>
Các vị trí mẫu hơi bất thường, nhưng một lợi ích là nội dung của bạn sẽ được hiển thị nếu JavaScript không chạy được. Mã này hiển thị một tiêu đề và đoạn văn mặc định chỉ được thay thế khi lớp Thành phần Web thực thi thành công:
<hello-world name="Craig"> <h1 slot="msgtext">Hello Default!</h1> <p>This text will become part of the component.</p> </hello-world>
Do đó, bạn có thể triển khai một số hình thức cải tiến liên tục – ngay cả khi đó chỉ là thông báo “Bạn cần JavaScript” !
DOM bóng khai báo
Các ví dụ trên tạo Shadow DOM bằng JavaScript. Đó vẫn là lựa chọn duy nhất, nhưng Shadow DOM khai báo thử nghiệm đang được phát triển cho Chrome. Điều này cho phép Hiển thị phía Máy chủ và tránh bất kỳ sự thay đổi bố cục hoặc nhấp nháy nào của nội dung chưa được định kiểu.
Mã sau được trình phân tích cú pháp HTML phát hiện, mã này tạo ra Shadow DOM giống hệt với DOM mà bạn đã tạo trong phần trước (bạn cần cập nhật thông báo nếu cần):
<hello-world name="Craig"> <template shadowroot="closed"> <slot name="msgtext" class="hw-text"></slot> <slot></slot> </template> <h1 slot="msgtext">Hello Default!</h1> <p>This text will become part of the component.</p> </hello-world>
Tính năng này không khả dụng trong bất kỳ trình duyệt nào và không có gì đảm bảo rằng nó sẽ đến được với Firefox hoặc Safari. Bạn có thể tìm hiểu thêm về Shadow DOM khai báo và một polyfill rất đơn giản, nhưng lưu ý rằng việc triển khai có thể thay đổi.
Sự kiện Shadow DOM
Thành phần Web của bạn có thể đính kèm các sự kiện vào bất kỳ phần tử nào trong Shadow DOM giống như bạn làm trong DOM trang, chẳng hạn như để lắng nghe các sự kiện nhấp chuột trên tất cả các phần tử bên trong:
shadow.addEventListener('click', e => { // do something });
Trừ khi bạn dừng Gắn thẻ, sự kiện sẽ xuất hiện trong DOM trang, nhưng sự kiện sẽ được nhắm mục tiêu lại. Do đó, nó dường như đến từ yếu tố tùy chỉnh của bạn hơn là các yếu tố bên trong nó.
Sử dụng các thành phần web trong các khung công tác khác
Bất kỳ Thành phần Web nào bạn tạo sẽ hoạt động trong tất cả các khung JavaScript. Không ai trong số họ biết hoặc quan tâm đến các phần tử HTML – thành phần <hello-world>
của bạn sẽ được coi như một <div>
và được đặt vào DOM nơi lớp sẽ kích hoạt.
custom-elements-everywhere.com cung cấp danh sách các khung và ghi chú Thành phần Web. Hầu hết đều hoàn toàn tương thích, mặc dù React.js có một số thách thức. Có thể sử dụng <hello-world>
trong JSX:
import React from 'react'; import ReactDOM from 'react-dom'; import from './hello-world.js'; function MyPage() { return ( <> <hello-world name="Craig"></hello-world> </> ); } ReactDOM.render(<MyPage />, document.getElementById('root'));
…nhưng:
- React chỉ có thể chuyển các kiểu dữ liệu nguyên thủy sang các thuộc tính HTML (không phải mảng hoặc đối tượng)
- React không thể lắng nghe các sự kiện của Thành phần Web, vì vậy bạn phải đính kèm các trình xử lý của riêng mình theo cách thủ công.
Các vấn đề và phê bình về thành phần web
Các thành phần Web đã được cải thiện đáng kể, nhưng một số khía cạnh có thể khó quản lý.
Khó khăn về tạo kiểu
Tạo kiểu cho các thành phần Web đặt ra một số thách thức, đặc biệt nếu bạn muốn ghi đè các kiểu có phạm vi. Có nhiều giải pháp:
- Tránh sử dụng Shadow DOM. Bạn có thể nối nội dung trực tiếp vào phần tử tùy chỉnh của mình, mặc dù bất kỳ JavaScript nào khác có thể vô tình hoặc độc hại thay đổi nó.
- Sử dụng
:host
các lớp. Như chúng ta đã thấy ở trên, CSS theo phạm vi có thể áp dụng các kiểu cụ thể khi một lớp được áp dụng cho phần tử tùy chỉnh. - Kiểm tra các thuộc tính tùy chỉnh CSS (biến). Thuộc tính tùy chỉnh xếp tầng thành các Thành phần Web, vì vậy, nếu phần tử của bạn sử dụng
var(--my-color)
, bạn có thể đặt--my-color
trong một vùng chứa bên ngoài (chẳng hạn như:root
) và nó sẽ được sử dụng. - Tận dụng các phần bóng đổ. Bộ chọn new :: part () có thể tạo kiểu cho một thành phần bên trong có thuộc tính part, tức là
<h1 part="heading">
bên trong một thành phần<hello-world>
có thể được tạo kiểu bằng bộ chọnhello-world::part(heading)
. - Chuyển vào một chuỗi các kiểu. Bạn có thể chuyển chúng như một thuộc tính để áp dụng trong một khối
<style>
.
Không có cách nào là lý tưởng và bạn sẽ cần lên kế hoạch cẩn thận cách những người dùng khác có thể tùy chỉnh Thành phần Web của bạn.
Đầu vào bị Bỏ qua
Mọi trường <input>
, <textarea>
hoặc <select>
trong Shadow DOM của bạn không được liên kết tự động trong biểu mẫu chứa. Những người chấp nhận Thành phần Web sớm sẽ thêm các trường ẩn vào DOM trang hoặc sử dụng giao diện FormData để cập nhật các giá trị. Cả hai đều không thực tế và phá vỡ tính đóng gói của Thành phần Web.
Giao diện ElementInternals mới cho phép Thành phần Web kết nối vào các biểu mẫu để các giá trị tùy chỉnh và hiệu lực có thể được xác định. Nó được triển khai trong Chrome, nhưng một polyfill có sẵn cho các trình duyệt khác.
Để chứng minh, bạn sẽ tạo thành phần <input-age name="your-age"></input-age>
cơ bản. Lớp phải có giá trị static formAssociated được đặt là true và tùy chọn, phương thức formAssociatedCallback () có thể được gọi khi biểu mẫu bên ngoài được liên kết:
// <input-age> web component class InputAge extends HTMLElement { static formAssociated = true; formAssociatedCallback(form) { console.log('form associated:', form.id); }
Phương thức khởi tạo bây giờ phải chạy phương thức attachmentInternals () , phương thức này cho phép thành phần giao tiếp với biểu mẫu và mã JavaScript khác muốn kiểm tra giá trị hoặc xác thực:
constructor() { super(); this.internals = this.attachInternals(); this.setValue(''); } // set form value setValue(v) { this.value = v; this.internals.setFormValue(v); }
Phương thức setFormValue () của ElementInternal đặt giá trị của phần tử cho biểu mẫu mẹ được khởi tạo bằng một chuỗi trống ở đây (nó cũng có thể được truyền vào một đối tượng FormData với nhiều cặp tên / giá trị). Các thuộc tính và phương pháp khác bao gồm:
- biểu mẫu : biểu mẫu mẹ
- nhãn : một mảng các phần tử gắn nhãn thành phần
- Các tùy chọn API xác thực ràng buộc như willValidate, checkValidity và validationMessage
Phương thức connectCallback ( ) tạo Shadow DOM như trước đây, nhưng cũng phải theo dõi trường để tìm các thay đổi, do đó, setFormValue () có thể được chạy:
connectedCallback() { const shadow = this.attachShadow({ mode: 'closed' }); shadow.innerHTML = ` <style>input { width: 4em; }</style> <input type="number" placeholder="age" min="18" max="120" />`; // monitor input values shadow.querySelector('input').addEventListener('input', e => { this.setValue(e.target.value); }); }
Bây giờ bạn có thể tạo một biểu mẫu HTML bằng Thành phần Web này hoạt động theo cách tương tự với các trường biểu mẫu khác:
<form id="myform"> <input type="text" name="your-name" placeholder="name" /> <input-age name="your-age"></input-age> <button>submit</button> </form>
Nó hoạt động, nhưng phải thừa nhận rằng nó cảm thấy hơi phức tạp.
Kiểm tra nó trong phần trình diễn CodePen
Để biết thêm thông tin, hãy tham khảo bài viết này về các điều khiển biểu mẫu có khả năng hơn.
Bản tóm tắt
Các thành phần Web đã phải vật lộn để đạt được sự đồng ý và chấp nhận vào thời điểm mà các khung JavaScript đã phát triển về tầm vóc và khả năng. Nếu bạn đến từ React, Vue.js hoặc Angular, Thành phần Web có thể trông phức tạp và rườm rà, đặc biệt khi bạn thiếu các tính năng như ràng buộc dữ liệu và quản lý trạng thái.
Có những khó khăn cần phải làm, nhưng tương lai cho Web Components rất tươi sáng. Chúng là một framework bất khả tri, nhẹ, nhanh và có thể triển khai các chức năng không thể thực hiện được nếu chỉ trong JavaScript.
Một thập kỷ trước, rất ít người có thể xử lý một trang web mà không có jQuery, nhưng các nhà cung cấp trình duyệt đã lấy các phần tuyệt vời và thêm các lựa chọn thay thế gốc (chẳng hạn như querySelector). Điều tương tự cũng sẽ xảy ra đối với các khung JavaScript và Thành phần Web là bước dự kiến đầu tiên.
Bạn có bất kỳ câu hỏi nào về cách sử dụng Web Components? Hãy nói về nó trong phần bình luận!
Tiết kiệm thời gian, chi phí và tối đa hóa hiệu suất trang web với:
- Trợ giúp tức thì từ các chuyên gia lưu trữ WordPress, 24/7.
- Tích hợp Cloudflare Enterprise.
- Tiếp cận khán giả toàn cầu với 34 trung tâm dữ liệu trên toàn thế giới.
- Tối ưu hóa với Giám sát Hiệu suất Ứng dụng được tích hợp sẵn của chúng tôi.
Tất cả những điều đó và hơn thế nữa, trong một kế hoạch không có hợp đồng dài hạn, hỗ trợ di chuyển và đảm bảo hoàn tiền trong 30 ngày. Kiểm tra các kế hoạch của chúng tôi hoặc nói chuyện với bộ phận bán hàng để tìm ra kế hoạch phù hợp với bạn.