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」として設計する感覚が大事