FNCT創造工学演習、予備実験向けにハンズオンを作成しました。
コンポーネントファイルの作成
componentsディレクトリに、新しくコンポーネントファイルを作成する。
ファイル名はTextInput.vue
としておく。
拡張子.vue
にすると、vue.jsの単一ファイルコンポーネントとして利用できる。
作成したファイルに、下記のコードを記述する。
<template>
<div>
<label>名前</label>
<input type="text" />
</div>
</template>
このコンポーネントを、HelloWorld.vue側に組み込んで使ってみる。
スクリプト部に下記のコードを追加しよう。
<script>
import TextInput from './TextInput'; // この行
export default {
name: 'HelloWorld',
components: { // この行
TextInput // この行
}, // この行
data() {
return {
...
}
</script>
最後に同じくHelloWorld.vueのテンプレート部に、下記のコードを追加する。
これでHTMLにテンプレートが挿入される。
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<TextInput /> <!-- この行 -->
...
</template>
このようにラベルとテキストボックスが表示されれば成功だ。
さらに連続コピペすれば、同一部品が使い回せているのが分かる。
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<TextInput /> <!-- この行 -->
<TextInput /> <!-- この行 -->
<TextInput /> <!-- この行 -->
...
</template>
パラメータを渡して、差し替え可能なつくりにする
このままだと「名前」というラベルしか表示できないので、そこを差し替えられるようにしたい。
今回はプロパティという仕組みを使って実現してみる。
まずはTextInput.vueを下のように修正する。
<label>
タグ内を修正し、下半分のスクリプト部をまるごと追加する。
<template>
<div>
<label>{{title}}</label> <!-- ここ -->
<input type="text" />
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: 'デフォルト'
}
}
}
</script>
加えて利用側のHelloWorld.vueを、下記のように修正する。
<TextInput title="名前" />
<TextInput title="メールアドレス" />
<TextInput />
これで、下のようにラベルが差し替えられたはずだ。
また3つめのようにlabel="..."
を省略すると、デフォルト
と表示されるようにもなっている。
見栄えを調整する
最後にスタイル記述を追加して、見栄えを調整してみよう。
TextInput.vueにスタイル部を追加(と、<div>
にクラスを追記)していく。
<template>
<div class="text-input"> <!-- classを追加 -->
...
</template>
<script>
...
</script>
<style scoped>
.text-input {
margin: 0 auto 20px;
width: 300px;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.text-input label {
color: #808080;
font-weight: bold;
}
.text-input input {
width: 100%;
padding: 5px 10px;
border: 1px solid #444;
border-radius: 3px;
}
</style>
簡単にスタイルを適用したが、結果はこのように表示される。
ここでポイントなのは<style scoped>
の部分。
scoped
記述があると、そこで書いたスタイルはファイル内のコンポーネントにだけ適用される。
サイト全体のスタイルを命名規則を統一して管理し、完成後も長期間にわたってそのルールを厳守してメンテしていくのは非常に大変なので、scoped
を適切に利用して管理する範囲を狭めてやることで、開発・運用にかかるコストを抑えていきたい。
単一ファイルコンポーネントのポイント
vue.jsの特徴的な機能のひとつである単一ファイルコンポーネントだが、このファイルは3つの要素から構成される。
- <template>
- <script>
- <style>
それぞれ、<template>
でHTMLの構造を、<script>
で実行すべき処理を、<style>
で見栄えを記述できる。
この3要素を組み合わせてひとつの部品を、さらに部品を組み合わせて複合された部品を作り上げていく。
こうして適切に分割された部品単位で開発していくことで、管理すべき対象を適切にスリム・シンプルにしていける。
そのほかの主な機能
vue.jsのコンポーネントの主な機能として、下記のようなものがある。
slot
親側で記述した内容を、コンポーネント側にそのまま挿入する。
$emit()
コンポーネントの親(この場合TextInputからHelloWorldに対して)イベントを発行する。
v-model
少々複雑になるが、props
と$emit()
を組み合わせると、v-model
という仕組みが実現できる。
今回の例でいうと、TextInputで入力されたテキストをHelloWorld側で簡単に使える(参照&設定ができる)ようになる。