入門から放棄へ:Web Components
15456 ワード
Web Componentsを検索しているのは誰ですか?
Web Componentsを検索するのは通常、Web Componentsを使用しないので、あなたと私のように、暇で勉強が好きで、あるいはフロントエンドの面接に対処しなければならないので、理解しなければなりません.
Web Componentsを使用しないのは多くの客観的な原因があります.例えば、あなたとWeb Componentsの間には約nつのフロントエンドフレームワークがあります.これらのフレームワークは面接の仕事に必要です.それらの大規模なアプリケーションに基づく実戦だけでなく、ソースコードの原理を理解する能力もあります.
だからWeb Componentsは自然にあなたのショートボードの一つになります.
なぜWeb Components
個人的にはここ数年の先端はずっと1つの問題をめぐっていると思います:コンポーネント化、例えば先端三国演義(React,Vue,Angular)の発展とその熱さは十分に説明していますが、1つの問題はずっと解決していません.それはコンポーネントの多重化の問題で、はっきり言ってどのように繰り返し車輪の問題を防止するかです.私はこれが問題だとは思いませんが、W 3 Cはこれが問題だと思っています.Web Componentsを勉強しなければなりません
W 3 Cの解決策は、仕様と基準を制定することによって、すべてのブラウザに一連のプラットフォームAPIを提供してカスタムHTMLラベルをサポートすることであり、これらのAPIに基づいて作成されたコンポーネントがすべてのサポートされているブラウザで実行され、コンポーネントの多重化を達成することができる.
Web Componentsの内容
W 3 Cやネット上の他の言論に洗脳されると、Web Componentsが未来だと信じ、どんな三国演義もそろっているので、Web Componentsをどのように書くかを知る必要があります.
まずWeb Componentsは4つの規範に基づいています:カスタム要素、影DOM、ESモジュール、HTMLテンプレート、私はあなたにやはり入らないことをお勧めします.規範は怠け者のおばあさんの足のように、臭いし、長いので、簡単なhello worldやtodoが必要です.
hello-world.js
hello-world.html
コンポーネントを くのは なことがわかりますが、 は あなたの の にはWeb Componentsの があります. に、 のコードと する と を します.
1.カスタム :
HTML Elementクラスを するだけで、カスタムラベル/ を できます.コンストラクション とライフサイクル は に されません.
2.HTMLテンプレート
HTMLタグには なスタイルとDOM、 DOMが まれています
HelloWorldクラスとテンプレートは も がなく、 DOMの の はHelloWorldクラスとテンプレートを し、サブDOMツリーとして することです. に DOMは、スタイルが されたり れたりしないことを し、モジュール されたパッケージを する.
3.グローバル コンポーネント
コンポーネント 、このjsファイルを することで、このWeb Componentsを することができます.
これで、 なWeb Componentsを するプロセスは、ほぼ できましたが、 で なプロジェクトに するには、より くのAPIサポートが です.
コンポーネントライフサイクル
1. constructor()
は されたがdocumentに されていない に され、 はステータスの 、イベントリスニング、シャドウDOMの に されます.
2. connectedCallback()
がDOMに されると され、 はデータを し、デフォルトのプロパティを するために されます.
3. disconnectedCallback()
がDOMから されると され、 はイベントのリスニングやタイマのキャンセルなどのクリーンアップ に されます.
4. attributeChangedCallback(name, oldValue, newValue)
が する の は されますが、 の を するとしますか?
my-attr が するとattributeChangedCallbackがトリガーされます
5. adoptedCallback()
カスタム が しいdocumentに されたときに されます.
Web Componentsに するほとんどの を っていますが、 し なTODOアプリケーションを る を てみましょう.
TODO
を に います.カスタムコンポーネントを2つ とします. to-do-app として を け れ、to-doを / /タグできます. to-to-item 、インデックス 、checked の
to-do-app.js
setterとgetterの により、 しいプロパティを します.
このアトリビュート に すと、to-doリストがレンダリングされます.
ボックスとボタンにイベントを する があります.
TOODを :
TODOアプリでtodoを できるようになりました.
とタグを するには、to-do-itemを する があります.js
to-do-item.js
で、renderTodolistではto-do-itemをレンダリングし め、 する にimportを とすると、これは たちが に ったESモジュールの です.
コンポーネントは、イベントによって コンポーネントに されます( ボタンとチェックボックス):
コンポーネントのリスニング:
コンポーネントのリスニング の :
ではtodo appの が しました
to-do-app.js
to-do-item.js
index.html
あきらめると した
が で べたように、あなたとWeb Componentsの にはそれらのフレームワークが てられており、Web Componentsも の の を していないし、ブラウザ の もあります(polyfillは えますが)、しばらくは めることをお めします.
Web Componentsを検索するのは通常、Web Componentsを使用しないので、あなたと私のように、暇で勉強が好きで、あるいはフロントエンドの面接に対処しなければならないので、理解しなければなりません.
Web Componentsを使用しないのは多くの客観的な原因があります.例えば、あなたとWeb Componentsの間には約nつのフロントエンドフレームワークがあります.これらのフレームワークは面接の仕事に必要です.それらの大規模なアプリケーションに基づく実戦だけでなく、ソースコードの原理を理解する能力もあります.
だからWeb Componentsは自然にあなたのショートボードの一つになります.
なぜWeb Components
個人的にはここ数年の先端はずっと1つの問題をめぐっていると思います:コンポーネント化、例えば先端三国演義(React,Vue,Angular)の発展とその熱さは十分に説明していますが、1つの問題はずっと解決していません.それはコンポーネントの多重化の問題で、はっきり言ってどのように繰り返し車輪の問題を防止するかです.私はこれが問題だとは思いませんが、W 3 Cはこれが問題だと思っています.Web Componentsを勉強しなければなりません
W 3 Cの解決策は、仕様と基準を制定することによって、すべてのブラウザに一連のプラットフォームAPIを提供してカスタムHTMLラベルをサポートすることであり、これらのAPIに基づいて作成されたコンポーネントがすべてのサポートされているブラウザで実行され、コンポーネントの多重化を達成することができる.
Web Componentsの内容
W 3 Cやネット上の他の言論に洗脳されると、Web Componentsが未来だと信じ、どんな三国演義もそろっているので、Web Componentsをどのように書くかを知る必要があります.
まずWeb Componentsは4つの規範に基づいています:カスタム要素、影DOM、ESモジュール、HTMLテンプレート、私はあなたにやはり入らないことをお勧めします.規範は怠け者のおばあさんの足のように、臭いし、長いので、簡単なhello worldやtodoが必要です.
hello-world.js
const template = document.createElement('template');
template.innerHTML = `
Hello: World
`;
class HelloWorld extends HTMLElement {
constructor() {
super();
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.appendChild(template.content.cloneNode(true));
this.$headline = this._shadowRoot.querySelector('h2');
this.$span = this._shadowRoot.querySelector('span');
}
connectedCallback() {
if(!this.hasAttribute('color')) {
this.setAttribute('color', 'orange');
}
if(!this.hasAttribute('text')) {
this.setAttribute('text', '');
}
this._render();
}
static get observedAttributes() {
return ['color', 'text'];
}
attributeChangedCallback(name, oldVal, newVal) {
switch(name) {
case 'color':
this._color = newVal;
break;
case 'text':
this._text = newVal;
break;
};
this._render();
}
_render() {
this.$headline.style.color = this._color;
this.$span.innerHTML = this._text;
}
}
window.customElements.define('hello-world', HelloWorld);
hello-world.html
Hello World Web Components
コンポーネントを くのは なことがわかりますが、 は あなたの の にはWeb Componentsの があります. に、 のコードと する と を します.
1.カスタム :
class HelloWorld extends HTMLElement {...}
HTML Elementクラスを するだけで、カスタムラベル/ を できます.コンストラクション とライフサイクル は に されません.
2.HTMLテンプレート
const template = document.createElement('template');
template.innerHTML = ...
HTMLタグには なスタイルとDOM、 DOMが まれています
this._shadowRoot = this.attachShadow({ mode: 'open' });
this._shadowRoot.appendChild(template.content.cloneNode(true));
HelloWorldクラスとテンプレートは も がなく、 DOMの の はHelloWorldクラスとテンプレートを し、サブDOMツリーとして することです. に DOMは、スタイルが されたり れたりしないことを し、モジュール されたパッケージを する.
3.グローバル コンポーネント
window.customElements.define('hello-world', HelloWorld);
コンポーネント 、このjsファイルを することで、このWeb Componentsを することができます.
これで、 なWeb Componentsを するプロセスは、ほぼ できましたが、 で なプロジェクトに するには、より くのAPIサポートが です.
コンポーネントライフサイクル
class MyElement extends HTMLElement {
constructor() {
// always call super() first
super();
console.log('constructed!');
}
connectedCallback() {
console.log('connected!');
}
disconnectedCallback() {
console.log('disconnected!');
}
attributeChangedCallback(name, oldVal, newVal) {
console.log(`Attribute: ${name} changed!`);
}
adoptedCallback() {
console.log('adopted!');
}
}
1. constructor()
は されたがdocumentに されていない に され、 はステータスの 、イベントリスニング、シャドウDOMの に されます.
2. connectedCallback()
がDOMに されると され、 はデータを し、デフォルトのプロパティを するために されます.
3. disconnectedCallback()
がDOMから されると され、 はイベントのリスニングやタイマのキャンセルなどのクリーンアップ に されます.
4. attributeChangedCallback(name, oldValue, newValue)
が する の は されますが、 の を するとしますか?
static get observedAttributes() {
return ['my-attr'];
}
my-attr が するとattributeChangedCallbackがトリガーされます
5. adoptedCallback()
カスタム が しいdocumentに されたときに されます.
Web Componentsに するほとんどの を っていますが、 し なTODOアプリケーションを る を てみましょう.
TODO
を に います.カスタムコンポーネントを2つ とします.
to-do-app.js
const template = document.createElement("template");
template.innerHTML = `
To do App
`;
class TodoApp extends HTMLElement {
constructor() {
super();
this._shadowRoot = this.attachShadow({ mode: "open" });
this._shadowRoot.appendChild(template.content.cloneNode(true));
this.$todoList = this._shadowRoot.querySelector("ul");
thisl.todos = [];
}
}
window.customElements.define("to-do-app", TodoApp);
setterとgetterの により、 しいプロパティを します.
set todos(value) {
this._todos = value;
this._renderTodoList();
}
get todos() {
return this._todos;
}
このアトリビュート に すと、to-doリストがレンダリングされます.
_renderTodoList() {
this.$todoList.innerHTML = "";
this._todos.forEach((todo, index) => {
let $todoItem = document.createElement("div");
$todoItem.innerHTML = todo.text;
this.$todoList.appendChild($todoItem);
});
}
ボックスとボタンにイベントを する があります.
constructor() {
super();
...
this.$input = this._shadowRoot.querySelector("input");
this.$submitButton = this._shadowRoot.querySelector("button");
this.$submitButton.addEventListener("click", this._addTodo.bind(this));
}
TOODを :
_addTodo() {
if(this.$input.value.length > 0){
this._todos.push({ text: this.$input.value, checked: false })
this._renderTodoList();
this.$input.value = '';
}
}
TODOアプリでtodoを できるようになりました.
とタグを するには、to-do-itemを する があります.js
to-do-item.js
const template = document.createElement('template');
template.innerHTML = `
`;
class TodoItem extends HTMLElement {
constructor() {
super();
this._shadowRoot = this.attachShadow({ 'mode': 'open' });
this._shadowRoot.appendChild(template.content.cloneNode(true));
this.$item = this._shadowRoot.querySelector('.item');
this.$removeButton = this._shadowRoot.querySelector('button');
this.$text = this._shadowRoot.querySelector('label');
this.$checkbox = this._shadowRoot.querySelector('input');
this.$removeButton.addEventListener('click', (e) => {
this.dispatchEvent(new CustomEvent('onRemove', { detail: this.index }));
});
this.$checkbox.addEventListener('click', (e) => {
this.dispatchEvent(new CustomEvent('onToggle', { detail: this.index }));
});
}
connectedCallback() {
// We set a default attribute here; if our end user hasn't provided one,
// our element will display a "placeholder" text instead.
if(!this.hasAttribute('text')) {
this.setAttribute('text', 'placeholder');
}
this._renderTodoItem();
}
_renderTodoItem() {
if (this.hasAttribute('checked')) {
this.$item.classList.add('completed');
this.$checkbox.setAttribute('checked', '');
} else {
this.$item.classList.remove('completed');
this.$checkbox.removeAttribute('checked');
}
this.$text.innerHTML = this._text;
}
static get observedAttributes() {
return ['text'];
}
attributeChangedCallback(name, oldValue, newValue) {
this._text = newValue;
}
}
window.customElements.define('to-do-item', TodoItem);
で、renderTodolistではto-do-itemをレンダリングし め、 する にimportを とすると、これは たちが に ったESモジュールの です.
_renderTodoList() {
this.$todoList.innerHTML = '';
this._todos.forEach((todo, index) => {
let $todoItem = document.createElement('to-do-item');
$todoItem.setAttribute('text', todo.text);
this.$todoList.appendChild($todoItem);
});
}
コンポーネントは、イベントによって コンポーネントに されます( ボタンとチェックボックス):
this.$removeButton.addEventListener('click', (e) => {
this.dispatchEvent(new CustomEvent('onRemove', { detail: this.index }));
});
this.$checkbox.addEventListener('click', (e) => {
this.dispatchEvent(new CustomEvent('onToggle', { detail: this.index }));
});
});
コンポーネントのリスニング:
$todoItem.addEventListener('onRemove', this._removeTodo.bind(this));
$todoItem.addEventListener('onToggle', this._toggleTodo.bind(this));
コンポーネントのリスニング の :
static get observedAttributes() {
return ["text", "checked", "index"];
}
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case "text":
this._text = newValue;
break;
case "checked":
this._checked = this.hasAttribute("checked");
break;
case "index":
this._index = parseInt(newValue);
break;
}
}
ではtodo appの が しました
to-do-app.js
import "./components/to-do-item";
const template = document.createElement("template");
template.innerHTML = `
Raw web components
To do
`;
class TodoApp extends HTMLElement {
constructor() {
super();
this._shadowRoot = this.attachShadow({ mode: "open" });
this._shadowRoot.appendChild(template.content.cloneNode(true));
this.$todoList = this._shadowRoot.querySelector("ul");
this.$input = this._shadowRoot.querySelector("input");
this.todos = [];
this.$submitButton = this._shadowRoot.querySelector("button");
this.$submitButton.addEventListener("click", this._addTodo.bind(this));
}
_removeTodo(e) {
this._todos.splice(e.detail, 1);
this._renderTodoList();
}
_toggleTodo(e) {
const todo = this._todos[e.detail];
this._todos[e.detail] = Object.assign({}, todo, {
checked: !todo.checked
});
this._renderTodoList();
}
_addTodo() {
if (this.$input.value.length > 0) {
this._todos.push({ text: this.$input.value, checked: false });
this._renderTodoList();
this.$input.value = "";
}
}
_renderTodoList() {
this.$todoList.innerHTML = "";
this._todos.forEach((todo, index) => {
let $todoItem = document.createElement("to-do-item");
$todoItem.setAttribute("text", todo.text);
if (todo.checked) {
$todoItem.setAttribute("checked", "");
}
$todoItem.setAttribute("index", index);
$todoItem.addEventListener("onRemove", this._removeTodo.bind(this));
$todoItem.addEventListener("onToggle", this._toggleTodo.bind(this));
this.$todoList.appendChild($todoItem);
});
}
set todos(value) {
this._todos = value;
this._renderTodoList();
}
get todos() {
return this._todos;
}
}
window.customElements.define("to-do-app", TodoApp);
to-do-item.js
const template = document.createElement("template");
template.innerHTML = `
`;
class TodoItem extends HTMLElement {
constructor() {
super();
this._shadowRoot = this.attachShadow({ mode: "open" });
this._shadowRoot.appendChild(template.content.cloneNode(true));
this.$item = this._shadowRoot.querySelector(".item");
this.$removeButton = this._shadowRoot.querySelector("button");
this.$text = this._shadowRoot.querySelector("label");
this.$checkbox = this._shadowRoot.querySelector("input");
this.$removeButton.addEventListener("click", e => {
this.dispatchEvent(new CustomEvent("onRemove", { detail: this.index }));
});
this.$checkbox.addEventListener("click", e => {
this.dispatchEvent(new CustomEvent("onToggle", { detail: this.index }));
});
}
connectedCallback() {
if (!this.hasAttribute("text")) {
this.setAttribute("text", "placeholder");
}
this._renderTodoItem();
}
static get observedAttributes() {
return ["text", "checked", "index"];
}
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case "text":
this._text = newValue;
break;
case "checked":
this._checked = this.hasAttribute("checked");
break;
case "index":
this._index = parseInt(newValue);
break;
}
}
_renderTodoItem() {
if (this.hasAttribute("checked")) {
this.$item.classList.add("completed");
this.$checkbox.setAttribute("checked", "");
} else {
this.$item.classList.remove("completed");
this.$checkbox.removeAttribute("checked");
}
this.$text.innerHTML = this._text;
}
set index(val) {
this.setAttribute("index", val);
}
get index() {
return this._index;
}
get checked() {
return this.hasAttribute("checked");
}
set checked(val) {
if (val) {
this.setAttribute("checked", "");
} else {
this.removeAttribute("checked");
}
}
}
window.customElements.define("to-do-item", TodoItem);
index.html
Web Components
あきらめると した
が で べたように、あなたとWeb Componentsの にはそれらのフレームワークが てられており、Web Componentsも の の を していないし、ブラウザ の もあります(polyfillは えますが)、しばらくは めることをお めします.