Halcyon Days

IT × 移住 × ファイナンス

MENU

駆け出しバックエンドエンジニアがフロントエンドエンジニアになることになったのでVue.jsのコンポーネントについて学ぶ

はじめに

「今後はフロントエンドを担当してもらうから」

上司から突然告げられたジョブチェンジ

まだまだPHPの経験値が足りないから基礎からしっかりやっていこうと思っていたタイミングで宣告だったので、 「まじか〜〜!」って感じでしたが、従うしかない。

これが社会。

人がいないから仕方がない。

自分は1年ほど前に少しJavaScriptを学んでいましたが、「jQueryって簡単に動きつけられるし、すげ〜〜」レベル。

フレームワークを学んだこともなければ、コンポーネントについても理解していない。

しかし、その前にTypeScriptもやらねばいけない。

そんなこんなで、日々頭がオーバーヒートしかけながらなんとか戦っています。

駆け出しバックエンドエンジニアが(ほぼ)未経験からフロントエンドエンジニアとして戦えるようになるまで学んだことを記録してやろうと思っています。

今回は初回なのでざっとまとめてみた。

コンポーネントの作り方

コンポーネント:機能を持ったHTML要素の設計図

コンポーネントの基本構成

下記のサンプルコードを参照にされたし。

<template>
  <div class="my-component">
    <h1>{{ title }}</h1>
    <input v-model="inputText" placeholder="Enter text" />
    <button @click="handleClick">Submit</button>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  name: 'MyComponent',
  data() {
    return {
      title: 'My Vue Component',
      inputText: ''
    };
  },
  methods: {
    handleClick() {
      console.log(this.inputText);
    }
  }
});
</script>

<style scoped>
.my-component {
  text-align: center;
}

button {
  margin-top: 10px;
}
</style>

基本的には、

  • template
  • script
  • style

の3つで構成されている。

<template></template>部分

ここに書かれたHTMLがブラウザ上に表示される。

<script></script>部分

コンポーネントのロジックを定義する部分で、データやメソッド、ライフサイクルフック、コンポーネントの設定などを定義する。 オブジェクトベースとクラスベースがある。

オブジェクトベース

オブジェクトリテラルコンポーネントを定義。

<script>
export default {
    name: 'MyComponent`,
    props: {
        title: {
            type: String,
            required: true
        }
    },
    data() {
        return {
            count: 0
        }
    },
    methods: {
        handleClick() {
            this.$emit('clicked', this.count++)
        }
    }
}
</script>

クラスベース

ぺんカルはこっち。 ES6のクラス構文を使って定義する。

<script lang='ts'>
import { Vue, Component, Prop, Emit }  from 'vue-property-decorator'

@Component
export default class MyComponent extends Vue {
    @Props({ required: true }) readonly title!: string

    count: number = 0

    @Emit('clicked')
    handleClick() {
        this.count++
        return this.count
    }
}
</script>

<style></style>部分

コンポーネントのスタイリングをする。

デコレータ

@Emit@Prop@はデコレータで、クラスやクラスのメソッド、プロパティに対して動作を付与するもの。

@Prop

コンポーネントから子コンポーネントにデータを渡すもの。

import { Vue, Component, Prop } from 'vue-propertiy-decorator'

@Component
export default MyComponent extends Vue {
    @Prop({ type: String, required: true }) title: string
}

上記のコードはtitleというプロパティを親コンポーネントから受け取ることができる。

@Emit

メソッドが実行された際にVueイベントを発火する。

import { Vue, Component, Emit } from 'vue-property-decorator'

@Component
export default class MyComponent extends Vue {
  @Emit('submit')
  handleSubmit() {
    return 'data to emit'
  }
}

handleSubmitメソッドが呼ばれると、Submitイベントが自動で発火されて親コンポーネントに追加される。

コンポーネントと子コンポーネント

ここがまーじでわからんので理解していく。

親 → 子: Propsでデータを渡す→親コンポーネントは子コンポーネントPropsを使ってデータを渡す。 子 → 親:イベントでデータを返す→子コンポーネント$emitを使ってイベントを発火し、親コンポーネントにデータやイベントを通知する。

サンプルコード

// 親コンポーネント
<template>
  <div>
    <h1>親コンポーネント</h1>
    <!-- 子コンポーネントへ "message" という Prop を渡す -->
    <ChildComponent :message="parentMessage" @updateMessage="handleUpdateMessage" />
    <p>子からのメッセージ: {{ childMessage }}</p>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import ChildComponent from './ChildComponent.vue';

@Component({
  components: {
    ChildComponent
  }
})
export default class ParentComponent extends Vue {
  parentMessage: string = '親からのメッセージ';
  childMessage: string = '';

  // 子コンポーネントから受け取ったメッセージを処理
  handleUpdateMessage(newMessage: string) {
    this.childMessage = newMessage;
  }
}
</script>
// 子コンポーネント
<template>
  <div>
    <h2>子コンポーネント</h2>
    <!-- 親から受け取った Props の表示 -->
    <p>親からのメッセージ: {{ message }}</p>
    <button @click="sendMessageToParent">親へメッセージを送る</button>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Prop, Emit } from "vue-property-decorator";

@Component
export default class ChildComponent extends Vue {
  // 親から渡された message プロパティを受け取る
  @Prop({ required: true }) message!: string;

  // 親にメッセージを送るためのメソッド
  @Emit('updateMessage')
  sendMessageToParent() {
    return '子からの新しいメッセージ';
  }
}
</script>

親と子をどうやって判断するか

親の特徴:他のコンポーネントを使用している、データを渡している、イベントをリッスンしている 子の特徴:propsを受け取っている、イベントを発火している

つまり、下記のように判断できる

  • テンプレート内で子コンポーネンが使われているかどうか
  • propsemitどちらを使っているか