1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

サクサクvue.jsで 単一ファイルコンポーネント(Single-file component)を使ってみる

Posted at

FNCT創造工学演習、予備実験向けにハンズオンを作成しました。

コンポーネントファイルの作成

componentsディレクトリに、新しくコンポーネントファイルを作成する。
スクリーンショット 2021-04-20 9.55.30.png

ファイル名はTextInput.vueとしておく。
拡張子.vueにすると、vue.jsの単一ファイルコンポーネントとして利用できる。
スクリーンショット 2021-04-20 9.56.52.png

作成したファイルに、下記のコードを記述する。

components/TextInput.vue
<template>
  <div>
    <label>名前</label>
    <input type="text" />
  </div>
</template>

このコンポーネントを、HelloWorld.vue側に組み込んで使ってみる。
スクリプト部に下記のコードを追加しよう。

components/HelloWorld.vue
<script>
import TextInput from './TextInput'; // この行

export default {
  name: 'HelloWorld',
  components: {       // この行
    TextInput         // この行
  },                  // この行
  data() {          
    return {       
...
}
</script>

最後に同じくHelloWorld.vueのテンプレート部に、下記のコードを追加する。
これでHTMLにテンプレートが挿入される。

components/HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <TextInput />   <!-- この行 -->          
    ...
</template>

このようにラベルとテキストボックスが表示されれば成功だ。

スクリーンショット 2021-04-20 11.55.16.png

さらに連続コピペすれば、同一部品が使い回せているのが分かる。

components/HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <TextInput />   <!-- この行 -->          
    <TextInput />   <!-- この行 -->          
    <TextInput />   <!-- この行 -->          
    ...
</template>

スクリーンショット 2021-04-20 11.56.32.png

パラメータを渡して、差し替え可能なつくりにする

このままだと「名前」というラベルしか表示できないので、そこを差し替えられるようにしたい。
今回はプロパティという仕組みを使って実現してみる。

まずはTextInput.vueを下のように修正する。
<label>タグ内を修正し、下半分のスクリプト部をまるごと追加する。

components/TextInput.vue
<template>
  <div>
    <label>{{title}}</label> <!-- ここ -->
    <input type="text" />
  </div>
</template>

<script>
export default {
    props: {
        title: {
            type: String,
            default: 'デフォルト'
        }
    }
}
</script>

加えて利用側のHelloWorld.vueを、下記のように修正する。

components/HelloWorld.vue
    <TextInput title="名前" />       
    <TextInput title="メールアドレス" /> 
    <TextInput />          

これで、下のようにラベルが差し替えられたはずだ。
また3つめのようにlabel="..."を省略すると、デフォルトと表示されるようにもなっている。

スクリーンショット 2021-04-20 12.02.09.png

見栄えを調整する

最後にスタイル記述を追加して、見栄えを調整してみよう。
TextInput.vueにスタイル部を追加(と、<div>にクラスを追記)していく。

components/TextInput.vue
<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>

簡単にスタイルを適用したが、結果はこのように表示される。

スクリーンショット 2021-04-20 13.56.52.png

ここでポイントなのは<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側で簡単に使える(参照&設定ができる)ようになる。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?