Web Componentsの属性(attributes)とは?
属性は
👉 「外のHTMLからコンポーネントに値を渡す仕組み」です。
Web Components 内で HTML から渡された属性(attributes)を取得する。
コポーネント側
class UserName extends HTMLElement {
connectedCallback() {
const name = this.getAttribute("name");
this.innerHTML = `<p>${name}</p>`;
}
}
利用側
<user-name name="山田"></user-name>
👉 利用側のHTMLで定義された値が、コンポーネントで利用できます。
後からJavascriptで属性を変更した場合の対応
後からJavascriptで属性を変更した場合:
el.setAttribute("name", "田中");
👉 そのままでは、画面は更新されません。
解決策:これに対応する為には、attributeChangedCallbackを使用します。
class UserName extends HTMLElement {
static get observedAttributes() {
return ["name"];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === "name") {
this.render();
}
}
connectedCallback() {
this.render();
}
render() {
const name = this.getAttribute("name") || "ゲスト";
this.innerHTML = `<p>${name}</p>`;
}
}
👉 これで、属性変更に追従できます。
attributes と properties を連携する
Web Conponentsにデータを渡す仕組みには、下記の2通りの方法があります。👇
- attributes → HTMLから値を渡す
- properties → JSから値を扱う
これらは、まったく別物です。
👉 そして重要なのは、この2つを正しく連動させるのが実務のコツです。
propertyとの連動(重要)
使い勝手を考えた場合、HTMLだけだと弱いので、JSからも操作できるようにします。
改良版
class UserName extends HTMLElement {
static get observedAttributes() {
return ["name"];
}
get name() {
return this.getAttribute("name");
}
set name(value) {
this.setAttribute("name", value);
}
attributeChangedCallback() {
this.render();
}
connectedCallback() {
this.render();
}
render() {
this.innerHTML = `<p>${this.name || "ゲスト"}</p>`;
}
}
👉 UserName クラスの name プロパティを通して、属性 name を操作可能とします。
使い方
const el = document.querySelector("user-name");
el.name = "佐藤";
👉 これにより、JavaScriptでも自然に扱えるようになります。
型の扱い(重要)
属性は全部「文字列」です。boolean や数字の扱いには注意が必要。
❌ NG
<my-flag active="false"></my-flag>
👉 "false" は truthy(文字列)の為、属性 active は false ではなく、常に true として判断されます。
✔ 対策
const active = this.hasAttribute("active");
👉 booleanは属性の「存在」で判断する。
実務テンプレ(コピペOK)
class MyElement extends HTMLElement {
static get observedAttributes() {
return ["value"];
}
get value() {
return this.getAttribute("value");
}
set value(v) {
if (v === null || v === undefined) {
this.removeAttribute("value");
} else {
this.setAttribute("value", v);
}
}
attributeChangedCallback() {
this.render();
}
connectedCallback() {
this.render();
}
render() {
// 描画処理
}
}
まとめ
属性の本質👇
- HTML → attribute
- JS → property
両方を同期するのが重要
👉 「外部API」として設計する感覚が大事