初めてのVue③コンポーネントの使用

初めてのVue③コンポーネントの使用

コードが複雑になるにつれ、どこに何を書いたかわからなくなる場合があります。そんな時にはコンポーネントという機能が大変便利です。コンポーネントを使うことで部品を組み立てるようにコードを使うことができるようになります。Vueを扱う上で必須の知識となるので、ぜひ理解しておきましょう。

この記事の対象者
  • コンポーネントって何?
  • Vueについて学びたい
  • templateを使いたい

コンポーネントの使い方

まずはコードです。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Document</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>
<body>
 <div id="app4">
//ポイント①:id="app4"の中で使えるapp-buttonを使います。
    <app-button>submit</app-button>
  </div>
<script>
let app4 = {
//ポイント②:componentによってapp-buttonでbuttonタグが使えるように定義します。
      components: {
        'app-button': {
          template: `
            <button :disabled="processing">
              <slot/>
            </button>
          `,
//ポイント③:dataによって変数を定義できます。
          data(){
            return{
              processing: true
            };
          }
        },
      }
    };
    Vue.createApp(app4).mount('#app4');
</script>
</body>
</html>

ブラウザでは↓のような感じです。

ポイントはコードの中に書いたとおりです。

書き方は覚えるしかないです。テンプレをコピペして修正するのが早いです。

コンポーネントの整理

コンポーネントが1つの時は気にならないのですが、複数になったときには各コンポーネントでファイルを作成した方がすっきりします。

そのために、まずはフォルダとファイルを作っていきます。

index.htmlと同じ階層にcomponentフォルダを作成してApp.jsとAppButton.jsファイルを作成しました。

ファイルの中身は下記の通りです。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Document</title>
  <script src="https://unpkg.com/vue@3"></script>
</head>
<body>
 <div id="app4">
    <app-button>submit</app-button>
  </div>
<script type="module">
//ポイント:App4をインポートしてマウントしています
  import App4 from "./js/components/App.js";
    Vue.createApp(App4).mount('#app4');
</script>
</body>
</html>
import AppButton from "./AppButton.js";
//ポイント:インポートしたAppButtonをapp-buttonとして使えるようにエクスポートしてます。
    export default {
      components: {
        'app-button': AppButton
      }
    };
//ポイント:AppButtonの具体的な中身はここで書きます。
export default {
    template: `
      <button :disabled="processing">
        <slot/>
      </button>
    `,

    data(){
      return{
        processing: true
      };
    }
}

このように分けることでコンポーネントが増えてもわかりやすくなります。

全てのコンポーネントを一度App.jsでまとめてindex.htmlに送るとするとコンポーネント一覧があるのでわかりやすいです。

密かなポイント

scriptタグにtype,moduleを設定しているのもポイントです。

モジュールタイプにしていないと下記のエラーが発生します。

Uncaught SyntaxError: Cannot use import statement outside a module (at (index):118:5)

これで綺麗になりました。

Propsについて

ついでにPropsについても学んでいきましょう。

コンポーネントのように複数のファイルにまたがってデータを渡すときに役立ちます。

まずはコードです。

<div id="app4">
    <app-button type="primary">submit</app-button> //タイプを追加
</div>
export default {
    template: `
      <button :disabled="processing">
        <slot/>
      </button>
    `,

//ここを追加
    props:{
      type: String
    }

    data(){
      return{
        processing: true
      };
    }
}

ブラウザのDevtoolで確認します。

typeにprimaryが設定されています。

primaryが文字列のためpropsではstringを設定しました。

次にデフォルトでprimaryになるように設定します。

<div id="app4">
    <app-button>submit</app-button>
</div>
props:{
      type: {
        type: String,
        default: 'primary'
      }
    },

ブラウザで確認します。

うまくいきました。

AppButton.jsのtypeがややこしいですが、最初のtypeがpropsの名前、後のtypeがpropsのタイプとなります。

classの追加

では、この機能を活かしてclassを追加してみます。

export default {
    template: `
      <button 
    ここを追加
        :class="{
          'border rounded px-5 py-2': true,
          'bg-blue-200': type === 'primary',
          'bg-green-200': type === 'secondary',
          'bg-red-200': type === 'third',
        }"
        :disabled="processing"
      >
        <slot/>
      </button>
    `,

    props:{
      type: {
        type: String,
        default: 'primary'
      }
    },

    data(){
      return{
        processing: true
      };
    }
}

CSSが反映されるようにindex.htmlに下記を追記します。

<script src="https://cdn.tailwindcss.com"></script>

ブラウザで確認します。

うまくいっています。

classに記入したCSSはboolean型となります。typeにprimaryを設定しているので青く表示されます。

ついでにdataの記述もpropsの中に入れてみます。

props:{
      type: {
        type: String,
        default: 'primary'
      }
      processing:{
        type: Boolean,
        default: true
      }
    },

    // data(){
    //   return{
    //     processing: true
    //   };
    // }

dataにアクセスしてもpropsにアクセスしても結果は同じになります。

今回はデータの受け渡しがなかったですが、親から子にデータを渡す時にはpropsをv-bindして渡すようになります。

いづれ出てくるのでお楽しみに!

関連記事