🤔

Vue 初心者が「computedって何!?」ってなった話+作ってみた

に公開

Vue.jsを業務で使うことになったので、
Vue自体や computed を理解するために、
「お届け先ジェネレーター(簡易版)」的なアプリを作ってみました!
ref や computed の使い方に迷いながらも、
UIとバリデーションをちょっとずつ整えていく流れをまとめています

使用環境:Vue SFC Playground

🌟やったことの概要

  • v-model を使って双方向データバインディングを体験
  • computed を使って、名前や住所の出力をまとめて算出
  • 郵便番号にバリデーションを追加
  • リセットボタン でフォームをクリアできるように

🧪最初に作ったやつ(template)

<template>
  <div>
    <h2>お名前ジェネレーター</h2>
    <input v-model="firstname" placeholder="名字">
    <input v-model="lastname" placeholder="名前">
    <br>
    <input v-model="postalCode" placeholder="郵便番号">
    <input v-model="address" placeholder="住所">
    <input v-model="city" placeholder="市町村">

    <p style="color: red;">正しい郵便番号を入れてね</p>
    <p>こんにちは!{{ fullname }} さん!</p>

    <p>お名前:{{ fullname }}</p>
    <p>お届け先:{{ fullAddress }}</p>

    <button @click="resetFrom">リセット</button>
  </div>
</template>

💡scriptの書き方と気づき

import { ref, computed } from 'vue';

const firstname = ref('');
const lastname = ref('');
const address = ref('');
const city = ref('');
const postalCode = ref('');

refってなに?

リアクティブな変数(状態)を作る関数!
ref() で作った変数は、Vue側が値の変更を監視してくれる!
→ v-modelと組み合わせると、入力に応じてリアルタイム更新ができる

computed()ってなに?

算出プロパティを定義する関数!
状態に依存して表示用の値を生成するときに便利!
例(Vue公式風)👇

const author = reactive({
  name: 'John Doe',
  books: ['Vue 2 Guide', 'Vue 3 Guide']
});

const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? 'Yes' : 'No';
});

実際に使ったところ👇

const fullname = computed(() => {
  return `${firstname.value} ${lastname.value}`.trim();
});

🚨バリデーションと住所のcomputed

郵便番号が 000-0000 のような形式じゃなかったら、
「正しく入力してね」って表示+住所出力もしないようにします!

const isPostalCodeValid = computed(() => {
  return /^\d{3}-\d{4}$/.test(postalCode.value);
});

const fullAddress = computed(() => {
  if (
    !isPostalCodeValid.value ||
    !postalCode.value ||
    !address.value ||
    !city.value
  ) {
    return ''; // 不正なときは空文字
  }
  return `${postalCode.value} ${address.value} ${city.value}`.trim();
});

✅バリデーションの表示方法(template)

<p v-if="postalCode && !isPostalCodeValid" style="color: red;">
  正しい郵便番号を入れてね
</p>

📦最終コードまとめ

<script setup>
import { ref, computed } from 'vue';

const firstname = ref('');
const lastname = ref('');
const address = ref('');
const city = ref('');
const postalCode = ref('');

// 名前
const fullname = computed(() => {
  return `${firstname.value} ${lastname.value}`.trim();
});

// 郵便番号バリデーション
const isPostalCodeValid = computed(() => {
  return /^\d{3}-\d{4}$/.test(postalCode.value);
});

// 住所
const fullAddress = computed(() => {
  if (
    !isPostalCodeValid.value ||
    !postalCode.value ||
    !address.value ||
    !city.value
  ) {
    return '';
  }
  return `${postalCode.value} ${address.value} ${city.value}`.trim();
});

// リセットボタン
const resetFrom = () => {
  firstname.value = '';
  lastname.value = '';
  address.value = '';
  city.value = '';
  postalCode.value = '';
};
</script>

<template>
  <div>
    <h2>お名前ジェネレーター</h2>
    <input v-model="firstname" placeholder="名字">
    <input v-model="lastname" placeholder="名前">
    <br>
    <input v-model="postalCode" placeholder="郵便番号">
    <input v-model="address" placeholder="住所">
    <input v-model="city" placeholder="市町村">
    <p v-if="postalCode && !isPostalCodeValid" style="color: red;">
      正しい郵便番号を入れてね
    </p>
    <p>こんにちは!{{ fullname }} さん!</p>
    <p>お名前:{{ fullname }}</p>
    <p>お届け先:{{ fullAddress }}</p>

    <button @click="resetFrom">リセット</button>
  </div>
</template>

✨感想

アウトプットとして書きました。
テンプレートとスクリプトの行き来が最初はちょっと混乱したけど、
v-model の便利さはすぐ実感できた!
今後は watch とか emit あたりも触っていきたいです。
refとかこれは何・・・?みたいな感じだったのが箱なんだ!と理解も深まったかなと思います。

💬まとめ

computed で表示用の処理を分けておくと、コードも読みやすくなるし超便利。

引き続き、もっと実用的なものも作ってみたいと思います。モーダルとか作ってみようかなとも思います。

Discussion