Web component ่ฎไฝ ่ชๅฎ HTML ๅ
็ด ( )๏ผๅฐ่ฃ ็ตๆงใ ๆจฃๅผๅ ่ก็บใ
๐ด ๐พ ๐ ๐ ๐ ๐ ๐ฅ โ
๐ ่ช่จๅ
็ด ( )
Copy // โญ๏ธ 1๏ธโฃ ๅฎฃๅ่ช่จๅ
็ด
class MyComponent extends HTMLElement {
// constructor
constructor() {
super();
// โญ๏ธ 2๏ธโฃ ๅปบ็ซ shadow DOM
this.attachShadow({ mode: 'open' }); // returns a reference to this.shadowRoot
// โญ๏ธ 3๏ธโฃ ๅปบ็ซๆจฃๆฟ 4๏ธโฃ ่ค่ฃฝๆจฃๆฟๅ
งๅฎนๅฐ shadow root
this.shadowRoot.innerHTML = `
<style> ... </style>
<div class="container"> ... </div>
`;
}// end of constructor()
}// end of MyComponent
// โญ๏ธ 5๏ธโฃ ่จปๅๆจ็ฑค โญโโtag nameโโโฎ โญโ class โโฎ
window.customElements.define('my-component', MyComponent);
๐ ่ช่จๅ
งๅปบๅ
็ด (customized built-in element )
Copy // โญ๏ธ customized built-in element
class FancyButton extends HTMLButtonElement {
constructor(){...}
}
// โญ๏ธ register new tag
// โญโโโ name โโโโฎ โญโ class โโฎ โญโโโโโโโโญ๏ธโโโโโโโโโฎ
customElements.define('fancy-button', FancyButton, {extends: 'button'});
1๏ธโฃ custom element 2๏ธโฃ shadow DOM 3๏ธโฃ template 4๏ธโฃ shadow root 5๏ธโฃ register
1๏ธโฃ ๅฎ็พฉ custom element
ๅ
ๅฎ็พฉไธๅ็นผๆฟ HTMLElement ็ ( )๏ผ
Copy // โญ๏ธ 1๏ธโฃ custom element
class MyComponent extends HTMLElement {
constructor() {
// โญ๏ธ ๅผๅซ็ถ้กๅฅ็ constructor
super();
// ๅจ้่ฃกๅๅงๅไฝ ็ component
}
}
2๏ธโฃ ๅปบ็ซ Shadow DOM
็บ web component ๅปบ็ซไธๅๅฐ่ฃ็ DOM ๆจน (encapsulated DOM tree )๏ผ่ฎๅ
ง้จ็ๆจฃๅผ ( styles) ๅ่
ณๆฌ ( scripts) ไธๆๅฝฑ้ฟๅฐๅค้ข ( ) ็ๅ
ถไป้จๅ๏ผๅไนไบฆ็ถใ
Copy constructor() {
super();
// โญ๏ธ 2๏ธโฃ ๅปบ็ซ shadow DOM
// mode:
// - 'open' : ๅ
่จฑ JS ๅพๅค้จ่จชๅ shadow DOM
// - 'closed': ไธๅ
่จฑ
this.attachShadow({ mode: 'open' });
}
3๏ธโฃ ๅปบ็ซๆจฃๆฟ๏ผไปฅไธๆไพไธๅๆนๅผ ๅปบ็ซ <template>
1: HTML 2: JS 3: static property
Copy <!-- โญ๏ธ 3๏ธโฃ ๅปบ็ซๆจฃๆฟ -->
<template id="my-component-template">
<!---------- โญ๏ธ ๅ
ง้จ็ๆจฃๅผ ---------->
<style>
.container {
border: 1px solid black;
padding: 10px;
}
</style>
<!---------- โญ๏ธ HTML ็ตๆง ---------->
<div class="container">
<h1>Hello from My Component!</h1>
<!-- โญ๏ธ "unnamed slot"๏ผ้ ็็ตฆไฝฟ็จ่
ๆๅ
ฅ่ช่จๅ
งๅฎน -->
<slot></slot>
</div>
</template>
๐ JS๏ผๆๅฐ 3๏ธโฃ 4๏ธโฃ ๅ
ฉๆญฅ้ฉๆฟ็ธฎๆ้ๆจฃ๏ผ
Copy // 1๏ธโฃ ๅฎฃๅ custom element
class MyComponent extends HTMLElement {
// constructor
constructor() {
super();
// 2๏ธโฃ ๅปบ็ซ shadow DOM
this.attachShadow({ mode: 'open' }); // returns a reference to this.shadowRoot
// โญ๏ธ 3๏ธโฃ ๅปบ็ซๆจฃๆฟ 4๏ธโฃ ่ค่ฃฝๆจฃๆฟๅ
งๅฎนๅฐ shadow root
this.shadowRoot.innerHTML = `
<style> ... </style>
<div class="container"> ... </div>
`;
}// end of constructor()
}// end of MyComponent
Copy class MyComponent extends HTMLElement {
// โญ๏ธ MyComponent.template
static get template() {
// ๅฆๆ้ๆฒๅๅงๅ๏ผๅท่กๅๅงๅ๏ผ็ถๅพๅฐ็ตๆๅญๅฐ
// ็งๆ้ๆ
ๅฑฌๆง(MyComponent._template)ไธญ
if (!this._template) { // this == MyComponent
// create <template> element
this._template = document.createElement("template");
// define template HTML structure
this._template.innerHTML = `...`;
}
return this._template;
}
// constructor
constructor() {
// ---- super init (HTMLElement) ----
super();
// ---- self init (MyComponent) ----
// โญ๏ธ attach shadow root
let root = this.attachShadow({ mode: "open" }); // root == this.shadowRoot
// โญ๏ธ clone template
let copy = MyComponent.template.content.cloneNode(true);
// โญ๏ธ add template copy to shadow root
root.appendChild(copy);
// other init process ...
}
}
4๏ธโฃ ๅฐๆจฃๆฟๅ ๅ
ฅ Shadow DOM
่ค่ฃฝๆจฃๆฟๅ
งๅฎน ๅฐ shadow root ๏ผ
Copy constructor() {
super();
this.attachShadow({ mode: 'open' }); // 2๏ธโฃ ๅปบ็ซ shadow DOM
// 3๏ธโฃ ๅปบ็ซ <template>
// โญ๏ธ 4๏ธโฃ ่ค่ฃฝๆจฃๆฟๅ
งๅฎนๅฐ shadow root
const template = document.getElementById('my-component-template');
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
ๆๅฐ 3๏ธโฃ 4๏ธโฃ ๅ
ฉๅๆญฅ้ฉๆฟ็ธฎๆ้ๆจฃ๏ผ
Copy // 1๏ธโฃ ๅฎฃๅ custom element
class MyComponent extends HTMLElement {
// constructor
constructor() {
super();
// 2๏ธโฃ ๅปบ็ซ shadow DOM
this.attachShadow({ mode: 'open' });
// โญ๏ธ 3๏ธโฃ ๅปบ็ซๆจฃๆฟ 4๏ธโฃ ่ค่ฃฝๆจฃๆฟๅ
งๅฎนๅฐ shadow root
this.shadowRoot.innerHTML = `
<style> ... </style>
<div class="container"> ... </div>
`;
}// end of constructor()
}// end of MyComponent
5๏ธโฃ ่จปๅ Component
็จ customElements.define()
่จปๅ web component ๏ผ
Copy // โญ๏ธ 5๏ธโฃ ่จปๅ Component โญโโtag nameโโโฎ โญโ class โโฎ
window.customElements.define('my-component', MyComponent);
่ช่จๅ
็ด ่ช่จๅ
งๅปบๅ
็ด ๐็ฏไพ
Copy <!-- โญ๏ธ custom element -->
<my-component>
<!-- slotted nodes -->
</my-component>
๐ JS๏ผๅฎ็พฉไธฆๅฎฃๅ
Copy // โญ๏ธ autonomous custom element ---------------
// autonomous๏ผ็จ็ซๅญๅจ็๏ผ้ๅ
งๅปบ็๏ผๅฆ๏ผHTMLButtonElement ็ญ๏ผ
class MyComponent extends HTMLElement {
// constructor
constructor() {
// tell HTMLElement to initialize itself.
super();
// get `width`, `height` attributes
const height = this.getAttribute('height') || '100px';
const width = this.getAttribute('width') || '100px';
// ...
}
// connected to document
connectedCallback() {
// attach shadow root
let root = this.attachShadow({mode: 'open'});
// โญ๏ธ clone nodes from <template>
let clone = tmpl.content.cloneNode(true);
root.append( clone );
// ...
}
// template HTML
static template(height, width) {
return `
<style>
.placeholder {
background-color: pink;
width: ${height};
height: ${width};
}
</style>
<div class='placeholder'>Placeholder</div>
`;
}
}
// โญ๏ธ register <my-component>
// โญ๏ธโญ๏ธ custom element names must contain a "hyphen".
// โญโโtag nameโโโฎ โญโ class โโฎ
customElements.define('my-component', MyComponent);
๐ JS๏ผๅฎ็พฉไธฆๅฎฃๅ
Copy // โญ๏ธ customized built-in element
class FancyButton extends HTMLButtonElement {
constructor(){...}
}
// โญ๏ธ register new tag
// โญโโโ name โโโโฎ โญโ class โโฎ โญโโโโโโโโญ๏ธโโโโโโโโโฎ
customElements.define('fancy-button', FancyButton, {extends: 'button'});
๐ HTML๏ผไฝฟ็จ ่ช่จๅ
งๅปบๅ
็ด (customized built-in element )
Copy <!-- โญ๏ธ customized built-in element -->
<!-- โญโโโ name โโโโฎ -->
<button is="fancy-button">some text</button>
๐ JS๏ผไฝฟ็จ ่ช่จๅ
งๅปบๅ
็ด
Copy // โญ๏ธ ๆนๆณใง๏ผ `new MyComponent()`
let button = new FancyButton();
// โญ๏ธ ๆนๆณไบ๏ผ `document.createElement('my-component')`
// โญโtagโโโฎ โญโโโโโโโโโญ๏ธโโโโโโโโโฎ
let button = document.createElement('button', {is: 'fancy-button'});
// customize
button.textContent = 'Fancy button!';
button.disabled = true;
// add to DOM tree
document.body.appendChild(button);