0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Day 21: Week 3 まとめ - コンポーネント化とスケーラビリティを振り返る

0
Last updated at Posted at 2025-12-20

この記事は「構造パスで作るシンプルなフロントエンドフレームワーク(Structive)」Advent Calendarの21日目です。
Structiveについて詳しくはこちらより

Week 3 を終えて

Week 3(Day 15〜20)では、コンポーネント化とスケーラビリティについて学びました。今日は、これまでの内容を振り返り、理解を深めます。

Week 3 で学んだこと

Day 15: SFC(シングルファイルコンポーネント)の設計思想

SFCの基本構造:

<template>
  <!-- HTML: UIの構造 -->
</template>

<style>
  /* CSS: スタイル */
</style>

<script type="module">
  // JavaScript: ロジックと状態
  export default class { }
</script>

なぜSFCなのか:

  • 関連コードが一箇所に集約
  • ファイル間の移動不要
  • コンポーネント単位で管理
  • 保守性と再利用性の向上

関心の分離:

  • template: 構造の関心
  • style: 見た目の関心
  • script: ロジックの関心

Day 16: Web Componentsとの統合

コンポーネントの登録(3ステップ):

  1. SFCファイルを作成
  2. Import Mapsで登録
<script type="importmap">
{
  "imports": {
    "@components/user-card": "./user-card.st.html"
  }
}
</script>
  1. Loaderを読み込み
<script type="module" src="EasyLoaders/components.js"></script>

ライフサイクル:

  • $connectedCallback: DOMに追加されたとき
  • $disconnectedCallback: DOMから削除されたとき

使用パターン:

export default class {
  timer = null;
  
  $connectedCallback() {
    // リソースの初期化
    this.timer = setInterval(() => { ... }, 1000);
  }
  
  $disconnectedCallback() {
    // リソースのクリーンアップ
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
  }
}

Day 17: 親子コンポーネント間のデータ受け渡し

状態の部分委譲:

<child-component data-bind="state.子パス:親パス"></child-component>

パスの変換:

親: users.*.name  →  子: user.name
親: users.*.age   →  子: user.age

子から親の状態変更:

// 子コンポーネント
export default class {
  product = { quantity: 1 };
  
  increase() {
    // 子で変更すると親の状態も変わる
    this["product.quantity"] += 1;
  }
}

複数プロパティの受け渡し:

<child 
  data-bind="
    state.item:items.*;
    state.index:$1;
    state.total:items.length
  "
></child>

Day 18: ビルトイン型WebComponentとShadow DOMモード

static $config:

export default class {
  static $config = {
    extends: "tr",           // ビルトイン要素の拡張
    shadowDomMode: "auto"    // Shadow DOMモード
  };
}

ビルトイン拡張(extends):

<!-- テーブル行を拡張 -->
<tr is="user-row" data-bind="state.user:users.*"></tr>

<!-- リストアイテムを拡張 -->
<li is="todo-item" data-bind="state.todo:todos.*"></li>

何がうれしいか:

  • HTMLの構造的制約を守れる
  • セマンティックなHTML
  • ブラウザのレイアウトエンジンが正しく動作

Shadow DOMモード:

  • auto: 可能なら使う、不可能なら通常DOM(推奨)
  • none: 常に通常DOM、グローバルCSSが適用される

Day 19: Import Mapsの詳細な使い方

3つのロードモード:

1. イージーロード(推奨)

<script type="importmap">
{
  "imports": {
    "@components/my-component": "./my-component.st.html"
  }
}
</script>
<script type="module" src="./EasyLoaders/components.js"></script>
  • Structiveコア不要
  • 最小限の記述

2. 自動ロード

<script type="importmap">
{
  "imports": {
    "structive": "./structive/core.js",
    "@components/my-component": "./my-component.st.html"
  }
}
</script>
<script type="module" src="./AutoLoaders/components.js"></script>
  • Structiveコア必要
  • 互換性のため

3. マニュアルロード

import { config, defineComponents } from "structive";

config.enableMainWrapper = false;
config.enableRouter = false;

defineComponents({
  "my-component": "my-component-module"
});
  • 細かい制御
  • 条件付きロード

Day 20: エラーコード体系とデバッグ

エラーコード形式:

PREFIX-NNN

主要な接頭辞:

  • TMP: テンプレート
  • BIND: バインディング
  • COMP: コンポーネント
  • STATE: 状態管理
  • FLT: フィルター
  • LIST: リスト管理
  • CSO: 親子間の状態

番号帯の意味:

  • 0xx: 初期化・設定
  • 1xx: 未登録・未検出
  • 2xx: 無効な値・フォーマット
  • 3xx: 状態の不一致
  • 4xx: ランタイム失敗

デバッグモード:

import { config } from "structive";
config.debug = true;

Week 3 の核心概念

1. SFCによるコンポーネント化

1ファイル = 1コンポーネント
  ├── template(構造)
  ├── style(見た目)
  └── script(ロジック)

利点:

  • コードの集約
  • 理解しやすさ
  • 保守性
  • 再利用性

2. Web標準の活用

SFC → Web Components → カスタム要素
  • Import Mapsで登録
  • customElements APIで実装
  • Shadow DOMでカプセル化

3. 状態の部分委譲パターン

親: users.*.name → state.user:users.* → 子: user.name
  • 構造パスで結合
  • 疎結合な設計
  • 双方向の同期

4. ビルトイン拡張の活用

<tr is="custom-row">
<li is="custom-item">
<option is="custom-option">
  • HTMLの制約を守る
  • セマンティック
  • ネイティブな動作

5. エラーコードによるデバッグ

BIND-101 → BINDの101番 → 未登録エラー
  • 素早い問題特定
  • 明確な修正方法
  • チーム内の共通言語

復習クイズ

Q1: SFCの3つのセクションは?

答え template(HTML)、style(CSS)、script(JavaScript)

Q2: コンポーネントのライフサイクルメソッドは?

答え `$connectedCallback`(DOMに追加)、`$disconnectedCallback`(DOMから削除)

Q3: 状態の部分委譲の構文は?

答え `data-bind="state.子パス:親パス"`

Q4: ビルトイン要素を拡張するには?

答え `static $config = { extends: "tr" }`を定義し、``で使用

Q5: 推奨されるロードモードは?

答え イージーロード(EasyLoader)。Structiveコア不要で最小限の記述。

Q6: エラーコードBIND-101の意味は?

答え BINDの未登録エラー。data-bindで参照した名前が登録されていない。

Week 1 + Week 2 + Week 3 = 完全な知識体系

Week 1(基礎編)

  • 構造パスの概念
  • UIと状態の思想
  • ボイラープレート排除
  • Proxyによるリアクティビティ

Week 2(コア機能編)

  • forブロックとループ
  • ifブロックと条件分岐
  • 属性バインディング
  • 派生状態(getter)
  • パイプフィルター

Week 3(応用編)

  • SFCの設計思想
  • Web Componentsとの統合
  • 親子コンポーネント
  • ビルトイン拡張
  • Import Maps
  • エラーコード体系

これで実用的なアプリケーションを構築できます!

実践的な開発フロー

1. プロジェクトのセットアップ

project/
  ├── index.html
  ├── components/
  │   ├── app-header.st.html
  │   ├── user-list.st.html
  │   └── user-card.st.html
  └── EasyLoaders/
      └── components.js

2. index.htmlの設定

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>My App</title>
  
  <script type="importmap">
  {
    "imports": {
      "@components/app-header": "./components/app-header.st.html",
      "@components/user-list": "./components/user-list.st.html",
      "@components/user-card": "./components/user-card.st.html"
    }
  }
  </script>
  
  <script type="module" src="./EasyLoaders/components.js"></script>
</head>
<body>
  <app-header></app-header>
  <user-list></user-list>
</body>
</html>

3. コンポーネントの実装

親コンポーネント(user-list.st.html):

<template>
  <div class="user-list">
    {{ for:users }}
      <user-card data-bind="state.user:users.*"></user-card>
    {{ endfor: }}
  </div>
</template>

<script type="module">
export default class {
  users = [
    { name: "Alice", email: "alice@example.com" },
    { name: "Bob", email: "bob@example.com" }
  ];
}
</script>

子コンポーネント(user-card.st.html):

<template>
  <div class="user-card">
    <h3>{{ user.name }}</h3>
    <p>{{ user.email }}</p>
  </div>
</template>

<style>
  .user-card {
    border: 1px solid #ccc;
    padding: 1em;
    margin-bottom: 1em;
  }
</style>

<script type="module">
export default class {
  user = { name: "", email: "" };
}
</script>

4. デバッグの有効化

// 開発環境
import { config } from "structive";
config.debug = true;

ベストプラクティスのまとめ

コンポーネント設計

✅ DO(推奨):

  • 1コンポーネント200行以下を目指す
  • 単一責任の原則を守る
  • 意味のある命名(user-card, product-list
  • デフォルト値を提供

❌ DON'T(非推奨):

  • 複数の責任を持つコンポーネント
  • 曖昧な命名(component1, thing
  • nullやundefinedを初期値にする

状態管理

✅ DO(推奨):

  • 基本状態と派生状態を明確に分ける
  • getterで計算ロジックを集約
  • 配列の更新はconcattoSpliced

❌ DON'T(非推奨):

  • 状態を複数箇所に分散
  • UIに複雑なロジックを書く
  • pushspliceで直接変更

親子関係

✅ DO(推奨):

  • 構造パスの契約を明確に
  • 子コンポーネントは独立させる
  • 双方向バインディングを活用

❌ DON'T(非推奨):

  • 親の内部構造に依存
  • グローバル状態に頼る
  • 複雑な親子通信

エラー対応

✅ DO(推奨):

  • エラーコードで素早く特定
  • config.debug = trueで詳細表示
  • ライフサイクルでエラーハンドリング

❌ DON'T(非推奨):

  • エラーを無視
  • try-catchなしの非同期処理
  • 不明瞭なエラーメッセージ

Week 4 への準備

Week 3までで、このフレームワークの主要機能はすべて学びました。Week 4では、実践的なトピックを扱います。

Week 4 の予定(Day 22〜24)

Day 22: 既存フレームワーク(React)との比較

  • コード量の比較
  • 開発体験の違い
  • パフォーマンス特性

Day 23: 既存フレームワーク(Vue)との比較

  • 設計思想の違い
  • テンプレート記法の比較
  • 学習曲線

Day 24: まとめ - 構造パスがもたらす開発体験の革新

  • 全体の振り返り
  • このフレームワークの特徴
  • 今後の展望

Week 3 の成果

習得した技術:

  • SFCによるコンポーネント化
  • Web標準の活用
  • 親子間のデータフロー
  • ビルトイン拡張
  • Import Mapsの使い方
  • エラーコード体系

実装できるようになったこと:

  • 再利用可能なコンポーネント
  • 階層化されたコンポーネントツリー
  • テーブル行などの特殊要素のコンポーネント化
  • 効率的なデバッグ

開発体験の向上:

  • コードの集約による保守性
  • Web標準による互換性
  • 構造パスによる疎結合
  • エラーコードによる素早いデバッグ

まとめ

Week 3では、コンポーネント化とスケーラビリティを学びました:

SFC(Day 15):

  • 1ファイル = template + style + script
  • 関心の分離とカプセル化

Web Components(Day 16):

  • Import Mapsで登録
  • EasyLoader/AutoLoader
  • ライフサイクル

親子コンポーネント(Day 17):

  • 状態の部分委譲
  • 構造パスで疎結合
  • 双方向の同期

ビルトイン拡張(Day 18):

  • static $config
  • HTMLの制約に対応
  • Shadow DOMモード

Import Maps(Day 19):

  • 3つのロードモード
  • 明示的な管理

エラーコード(Day 20):

  • PREFIX-NNN形式
  • 素早い問題特定
  • デバッグモード

これで大規模アプリケーションの開発準備が整いました!

Week 4では、既存フレームワークとの比較を通じて、このフレームワークの特徴をより深く理解していきます。


次回: Day 22「既存フレームワーク(React)との比較」

Week 3 お疲れさまでした!分からないことがあればコメントで質問してください。
Week 4 で既存フレームワークとの比較を学んでいきましょう!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?