Vue.jsでWebページをつくる際の肝!「コンポーネント」をTypeScriptで活用しよう
TypeScriptで学ぶJavaScriptフレームワーク「Vue.js」の利用法 第6回
ダウンロード サンプルファイル (180.1 KB)
コンポーネントで双方向データバインディングを実装
propsとemitを組み合わせることで、コンポーネントに対して双方向データバインディングを設定できます。図3のサンプルでは、子コンポーネント内のテキストボックスと、子コンポーネント外のテキストボックスの内容が同期して変更されます。
親コンポーネントには、PhoneFormコンポーネントをリスト6の通り記述します。
<PhoneForm v-model="paramName" v-model:vendor="paramVendor" v-model:price="paramPrice"></PhoneForm>
(1)で、PhoneFormコンポーネントの引数にv-modelディレクティブで変数をバインディングしています。ディレクティブには「v-model」のほか、「v-model:vendor」「v-model:price」の通りプロパティ名を指定することもできます。
対応する子コンポーネントはリスト7の通りです。
<template>
<!-- inputタグだけ抽出して記述 ...(1)-->
<input type="text" :value="modelValue" @input="onUpdateModelValue">
<input type="text" :value="vendor" @input="onUpdateVendor">
<input type="number" :value="price" @input="onUpdatePrice">
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
props: { // ...(2)
modelValue: String, // v-modelで指定した名前
vendor: String, // v-model:vendorで指定したメーカー
price: Number // v-model:priceで指定した価格
},
emits: [ // ...(3)
'update:modelValue',
'update:vendor',
'update:price'
],
setup(props, context) {
const onUpdateModelValue = ((e: Event) => { // ...(4)
if (e.target instanceof HTMLInputElement) {
context.emit('update:modelValue', e.target.value)
}
})
(以下略:vendor、priceのイベントハンドラー)
}
})
v-modelディレクティブで指定されるプロパティは(2)のpropsに記述します。「v-model:vendor」や「v-model:price」のように、コロンの後ろに名前が指定されたディレクティブに対応するプロパティはその名前になります(「vendor」、「price」)。名前が指定されない「v-model」ディレクティブに対応するプロパティは「modelValue」になる決まりです。同様にemits(3)に指定するイベント名も、「v-model:vendor」「v-model:price」に対応するイベント名はそれぞれ「update:vendor」「update:price」、「v-model」に対応するイベント名は「update:modelValue」となります。
コンポーネントのinputタグ(1)では、(2)のプロパティを:value(v-bind:valueの省略記法)ディレクティブに指定してデータを反映するとともに、@input(v-on:inputの省略記法)ディレクティブに(4)のイベントハンドラーを指定して、文字入力時に(3)のイベントをemitすることで、双方向データバインディングの動作が実現します。
<script setup>で記述を簡略化
これまでの記述は、<script setup>を利用してさらに簡略化できます。以下ではポイントだけを説明します。全てのコードはp002a-emit-setupサンプルを参照してください。
参照するコンポーネントの指定
<script setup>を利用しない場合、参照するコンポーネントをdefineComponentのcomponentsに設定していました。<script setup>を利用する場合、コンポーネントをインポートするだけで、そのコンポーネントが利用できるようになります。
<script setup lang="ts"> // importするだけでコンポーネントが利用できる import PhoneWithBuy from "./components/PhoneWithBuy.vue" (略) </script>
プロパティ、emitの指定
<script setup>を利用しない場合、プロパティやemitは、defineComponentのprops、emitで指定していました。<script setup>を利用する場合、プロパティはリスト9(1)のdefinePropsメソッド、emitは(2)のdefineEmitsメソッドで取得して、(3)の通り利用できます。
const props = defineProps({ // ...(1)
phoneData: PhoneData // PhoneData型プロパティ
})
const emit = defineEmits([ // ...(2)
'onBuy' // emitする可能性があるイベントを指定
])
const onClickBuyButton = (() => {
emit('onBuy', props.phoneData) // ...(3)
})
コンポーネント内部のHTML要素を指定するスロット
最後に、コンポーネントタグの内側に記述された内容を画面に反映する「スロット」を、タイトルと内容の文言からなるエラー表示を行う図4のサンプルで説明します。
図4の内容を表示するCustomErrorコンポーネントは、リスト10の通りです。スロットには名前なしのもの(1)と名前付きのもの(2)があります。
<template>
<div class="error">
<div class="title">
<slot></slot> <!-- 名前なしスロット ...(1)-->
</div>
<div class="description">
<slot name="desc"></slot> <!-- 名前付きスロット ...(2)-->
</div>
</div>
</template>
コンポーネントを利用する側の実装は、リスト11の通りです。<CustomError>の内側で、名前がついていない(1)がリスト10(1)の名前なしスロットに、v-slotで名前(desc)がついている(2)の内容がリスト10(2)の名前付きスロットに設定されます。
<template>
<CustomError>
名前なしスロットに渡されます。 <!--(1)-->
<template v-slot:desc> <!--(2)-->
名前付きスロットに渡されます。
</template>
</CustomError>
</template>
まとめ
本記事では、Vue.jsでWebページを構成するコンポーネントの記述・利用法を説明しました。Webページを小さいコンポーネントに分割して、プロパティでコンポーネントにデータを設定したり、emitでコンポーネントからイベントを発行したりできます。
次回は、複数のページを切り替え表示するVue.jsのルーティングについて説明します。
参考資料
この記事は参考になりましたか?
既に会員の方はを行ってください。
- TypeScriptで学ぶJavaScriptフレームワーク「Vue.js」の利用法連載記事一覧
-
- TypeScriptとも相性抜群なライブラリ──Vue.jsで状態管理を行う新定番「Pin...
- Vue.jsでページを切り替える「Vue Router」の利用法を解説! TypeScri...
- Vue.jsでWebページをつくる際の肝!「コンポーネント」をTypeScriptで活用し...
- この記事の著者
-
WINGSプロジェクト 吉川 英一(ヨシカワ エイイチ)
<WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
山田 祥寛(ヤマダ ヨシヒロ)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
