6 ポイント 投稿者 GN⁺ 2024-04-27 | 2件のコメント | WhatsAppで共有

HTML属性とDOMプロパティの違い

HTML属性とDOMプロパティは本質的に別物である。同じ名前の属性とプロパティを持つことはあるが、それぞれに異なる値を設定できる。

  • 属性とプロパティの主な違い

    • HTMLシリアライズ: 属性はHTMLとしてシリアライズされるが、プロパティはされない
    • 値の型: 属性の値は常に文字列だが、プロパティはあらゆる型になり得る
    • 大文字・小文字の区別: 属性名は大文字・小文字を区別しないが、プロパティ名は区別する。ただし属性値は大文字・小文字を区別する
  • リフレクション(Reflection)

    • 利便性のため、ほとんどの仕様は定義されたすべての属性に対してプロパティの等価物を作る
    • プロパティが属性を反映するとき、属性がデータのソースになる。属性を設定するとプロパティが更新され、プロパティを読むと属性を読む
    • ただし一部のリフレクターはより複雑で、属性名と反映先のプロパティ名が異なることもある
  • バリデーション、型変換、デフォルト値

    • 属性にはバリデーションとデフォルト値があるが、プロパティにはない
    • 一部のプロパティは型変換を行う
  • inputフィールドのvalue

    • value属性とvalueプロパティがあるが、valueプロパティはvalue属性を反映しない。代わりにdefaultValueプロパティがvalue属性を反映する
    • valueプロパティはいかなる属性も反映しない。これは珍しいことではなく、offsetWidthparentNodeなど多くのプロパティがそうである
    • valueプロパティは最初はdefaultValueプロパティに従う。その後、JavaScriptやユーザー操作によってvalueプロパティが設定されると、内部値へ切り替わる
  • 属性は構成のためのものであるべき

    • 属性は構成のためのものであるべきで、プロパティは状態を保持できるべきである
    • light-DOMツリーは単一の所有者を持つべきである
    • <details>要素と<dialog>要素は、open状態をopen属性で表し、ブラウザはユーザー操作への応答としてこの属性を自動的に追加・削除する。これは設計上のミスだと考えられる
  • フレームワークごとの差異の扱い

    • PreactとVueJSは、propName in elementであればpropをプロパティとして設定し、そうでなければ属性を設定する。属性よりもプロパティを優先する
    • Reactはその逆を行う。プロパティを優先するよう事前定義されたケースを除き、属性を設定する
    • lit-htmlは属性とプロパティの区別を維持しており、属性ではなくプロパティを設定するには名前の前に.を付ける必要がある

GN⁺の意見

  • HTML属性とDOMプロパティの違いを理解することは、低レベルのDOM操作では重要である。多くの場合は大きな差はないが、フレームワークを使う際には注意が必要

  • 属性は設定(configuration)、プロパティは状態(state)を表すものとして区別するのが望ましいように見える。最近の一部HTML要素ではこれが守られておらず、残念である

  • 特にReactでカスタム要素を使うときは注意が必要である。Reactはカスタム要素のプロパティを、プロパティではなく属性として設定するため、プロパティ専用のものは動作しない可能性がある。これはReact 19で改善される予定

  • Preact、Vue、React、lit-htmlなど主要フレームワークが属性とプロパティをどう扱うかを比較してみるのも興味深い。各フレームワークの思想や設計判断が反映されている

  • Web標準とブラウザ実装は、常に開発者フレンドリーとは限らない。<input>要素のvalue属性とプロパティのようなケースが代表例である。下位互換性のため簡単には変えられないだろうが、今後はもう少し一貫性のある設計になってほしい

2件のコメント

 
superwoou 2024-04-27

attribute と property を同じ「属性」として訳してしまいましたね..