frontendBaby

公開日

- 11 分で読めます

第7話 「Component型って何だろう?」


どうしてもVue.jsが分からないので森の博士の研究所に押しかけてみたら、人生が激変した子タヌキの話

この物語は、フロントエンド技術を楽しく学ぶことを目的に、生成AIを活用して執筆されています。 技術的な情報の正確性には細心の注意を払っていますが、その内容がすべて真実であることを保証するものではありません。 あくまで学習の補助ツールとして、肩の力を抜いてお楽しみください。


登場人物紹介

  • フロントエンド博士: 森の奥の研究所に住む、フロントエンドのことなら何でも知っている物知り博士。ポン吉の素朴な疑問にいつも優しく(そして面白おかしく)答えてくれる。
  • ポン吉: 好奇心旺盛な子タヌキ。将来の夢はフロントエンドエンジニア。最近Vue.jsを学び始めたが、その奥深さに興味津々。新しい知識をゲットすると、思わず「ポン!」と飛び跳ねる特技あり。

第7話🦝「Component型って何だろう?」

createAppが厳密な型定義によって守られていることを知ったポン吉。今日はその引数であるComponent型の謎を解き明かすため、意気揚々と研究所にやってきた。

ポン吉: 「博士!Component型について教えてください!僕らがいつも書いている、あのオブジェクトのことですよね?」

博士: 「うむ、その通りじゃ、ポン吉。Component型とは、Vue.jsにおける『部品』の設計図。我々がdatamethodscomputedなどを書く、あのオブジェクトの『あるべき姿』を定義したものがComponent型なんじゃよ。」

博士は、Component型のオブジェクトの例をモニターに映し出した。

const MyComponent = {
  props: {
    name: String
  },
  data() {
    return {
      message: 'こんにちは!'
    }
  },
  methods: {
    greet() {
      alert(this.message + ' ' + this.name)
    }
  },
  computed: {
    reversedName() {
      return this.name.split('').reverse().join('')
    }
  }
}

博士: 「このオブジェクトが、Component型の一つの具体例じゃ。propsdatamethodsといった、おなじみのプロパティがたくさん詰まっておるな。」

ポン吉: 「あ! dataとかmethodsっていう言葉、見たことあります!僕がいつも書くのは<script setup>という形式が多いので、こんな風に全部を一つのオブジェクトにまとめるのは新鮮です。でも、使われているキーワードは似ていますね!これらがComponent型で決められたルールなんですね!」

博士: 「そういうことじゃ。Component型は、いわば『Vueコンポーネントなら、こういうプロパティを持っていていいですよ』というルールを定めた、大きな器のようなものなんじゃ。」

博士は、Component型の概念的な構造を黒板に描いた。

// Component型のイメージ(簡略版)
interface Component {
  props?: object | string[];
  data?: (this: ComponentPublicInstance) => object;
  methods?: { [key: string]: Function };
  computed?: { [key: string]: Function | { get: Function; set: Function } };
  setup?: (props: Props, context: SetupContext) => object | Function;
  // ...他にもたくさん!
}

ポン吉: 「うわー!やっぱり、propsとかdataとか、僕が知ってる名前がたくさんあります!setupっていうのもありますね!」

博士: 「そうじゃな。このComponent型があるおかげで、我々がもしmetodsと書くところをmethodとタイポしてしまったり、dataを関数ではなくオブジェクトで書いてしまったりした時に、TypeScriptが『それはComponent型のルールに反しているよ!』と教えてくれるんじゃ。」

ポン吉: 「なるほど!Componentというお手本があるから、間違いに気づけるんですね!」

博士: 「その通り。これはオブジェクト指向という考え方に少し似ておる。特定の役割を持つ『モノ』(オブジェクト)が、どんなデータ(プロパティ)を持ち、どんな振る舞い(メソッド)をすべきかを、あらかじめ決めておく、という考え方じゃ。」

ポン吉: 「プロパティとメソッド…?」

博士: 「うむ。ざっくり言うと、dataのように『状態や情報』を表すのがプロパティで、methodsの中の関数のように『動きや処理』を表すのがメソッドじゃな。」

ポン吉は、自分が書いていたコンポーネントが、Componentというしっかりとした型定義の上で成り立っていたことを知り、深く納得した。

ポン吉: 「コンポーネントって、ただのオブジェクトじゃなくて、Vue.jsが決めたルールに沿った、特別な部品だったんですね!ポン!」

博士: 「その通りじゃ!そして、実はこのComponent型、前回見たcreateAppの型定義のように、ジェネリクスを使った、さらに奥深い姿も持っておるんじゃよ。」

ポン吉: 「えっ!またあの<...>が出てくるんですか!?」

博士: 「ふふふ。その話は、また次回にしようかの。次回は、Component型が持つ、7つの不思議なパラメータの謎に迫ってみよう。」

ポン吉: 「7つも!?はい、気になります!」

ポン吉の探求は、いよいよVue.jsとTypeScriptの核心へと近づいていく。


🌟 今日のまとめ

  • Component は、Vueコンポーネントが持つべきプロパティ(data, propsなど)を定義した、いわば「設計図」。
  • この型のおかげで、コンポーネントの書き間違いをTypeScriptがチェックしてくれる。
  • オブジェクトが持つ「状態や情報」を プロパティ、「動きや処理」を メソッド と呼ぶことがある。
  • いつも書いているコンポーネントは、Componentという型に守られた、特別なオブジェクトだった。

次回予告 「7つの不思議なパラメータ」

Component型は、実はComponent<P, B, D, C, M, E, S>という、7つのジェネリックパラメータを持つ複雑な型だった!ポン吉と一緒に、この謎のアルファベットの正体を解き明かしましょう!

👨‍🏫 博士からの補足

次回予告で「7つの不思議なパラメータ」と言ったが、ポン吉は少し不安になっているかもしれんな。じゃが安心するんじゃ。今日はその正体を少しだけ、こっそり教えてしまおう。

実は、Component型の正式な定義は、こんな姿をしておるんじゃ:

Component<P, B, D, C, M, E, S>

この7つのアルファベットは、それぞれVueコンポーネントの大切な要素を表しておる:

  • P = Props(プロパティ) - 親から受け取るデータ
  • B = RawBindings(生のバインディング) - setup関数から返される値
  • D = Data(データ) - コンポーネントの状態
  • C = Computed(算出プロパティ) - 計算して求める値
  • M = Methods(メソッド) - コンポーネントの動作
  • E = Emits(イベント) - 親に送るメッセージ
  • S = Slots(スロット) - 中身を差し替えられる部分

ポン吉が今まで書いてきたdatamethodsも、実はこの大きな設計図の一部だったんじゃな!

今日の話で出てきた「オブジェクトのプロパティとメソッド」というのも、実はこのD(Data)とM(Methods)に対応しておる。そして、ポン吉が普段使っている<script setup>で書く変数や関数も、この型システムによってしっかりと管理されておるんじゃよ。

もちろん、今はこの7つすべてを覚える必要はないぞい。ポン吉が普段通りにコンポーネントを書いていれば、Vue.jsが裏でこの複雑な型の管理を全部やってくれるからな。

興味深いことに、この7つのパラメータは、Vue.jsが進化する過程で少しずつ増えていったものなんじゃ。最初はもっとシンプルだったのが、開発者のニーズに応えて、より柔軟で強力な型システムに発展していったんじゃよ。

じゃが、いつかポン吉が「もっと複雑なコンポーネントを作りたい」「チームで大きなアプリを作りたい」と思った時、この7つの要素を意識できるようになると、まさにコンポーネントの設計師として、一段上のレベルに到達できるはずじゃ。


第7話 おわり