シェルスクリプトマガジン

作りながら学ぶVue.js入門(Vol.100掲載)

著者:大津 真

JavaScriptフレームワークの中でも、学びやすさと柔軟さで人気を集めている「Vue.js」。本連載では、Vue.jsの基礎から実践的な使い方までを、分かりやすく丁寧に解説していきます。一緒にフロントエンド開発の楽しさを体験してみましょう。第5回では、v-modelディレクティブによる双方向データバインディングと、計算結果をプロパティとして返す算出プロパティについて説明します。

シェルスクリプトマガジン Vol.100は以下のリンク先でご購入できます。

図1 「v-model1/src/App.vue」ファイルのコード

<script setup>
import { ref } from 'vue'

// refでリアクティブな変数を定義
const message = ref('こんにちは')   ←①
</script>

<template>
  <div>
    <h2>Composition APIでv-modelのテスト</h2>
    <!-- v-modelを使って入力値とリアクティブ変数を同期 -->
    <input v-model="message" placeholder="入力してみてください" />  ←②
    <button @click="message = ''">クリア</button> ←③
    <p>入力されたメッセージ: {{ message }}</p>  ←④
  </div>
</template>

図5 v-modelディレクティブを使う場合と使わない場合のコードの比較

■v-modelディレクティブを使う場合
<input v-model="message" placeholder="入力してみてください" />

■v-modelディレクティブを使わない場合
<input
  v-bind:value="message"
  v-on:input="message = $event.target.value"
  placeholder="入力してみてください"
/>

図6 「kaibun1/src/App.vue」ファイルのコード

<template>
  <div>
    <h2>入力した文字列が回文かどうかを判断</h2>
    <input v-model="message" placeholder="たけやぶやけた" />
    <button @click="checkKaibun">判定</button>
    <button @click="clearInput">クリア</button>
    <p>入力されたメッセージ: {{ message }}</p>
    <p>{{ result }}</p>
  </div>
</template>
<script setup>
import { ref } from 'vue'

const message = ref('')
const result = ref('') // 判定結果を表示する文字列
// 回文判定関数(ボタンを押したときに実行)
function checkKaibun() { 
  if (!message.value) {
    result.value = '文字を入力してください。'
    return
  }
  // 文字列を反転して比較
  const reversed = message.value.split('').reverse().join('') 
  if (message.value === reversed) { 
    result.value = '✅ 回文です!'
  } else {
    result.value = '❌ 回文ではありません。'
  }
}
// 入力クリア
function clearInput() {
  message.value = ''
  result.value = ''
}
</script>

図10 「computed-prop1/src/App.vue」ファイルのコード

<template>
  <div>
    <h2>算出プロパティなし(直接式)</h2>
    <input v-model="firstName" placeholder="名" />  ←①
    <input v-model="lastName" placeholder="姓" /> ←②
    <!-- マスタッシュ構文に直接式を書く -->
    <p>フルネーム:{{ firstName + ' ' + lastName }}</p> ←③
  </div>
</template>
<script setup>
import { ref } from 'vue'

const firstName = ref('')
const lastName = ref('')
</script>

図11 「computed-prop2/src/App.vue」ファイルのコード

<template>
  <div>
    <h2>算出プロパティ(computed)を使って整理</h2>
    <input v-model="firstName" placeholder="名" />
    <input v-model="lastName" placeholder="姓" />
    <!-- シンプルに変数名として使用 -->
    <p>フルネーム:{{ fullName }}</p>
  </div>
</template>
<script setup>
import { ref, computed } from 'vue'

const firstName = ref('')
const lastName = ref('')
const fullName = computed(() => {
  return ${firstName.value} ${lastName.value}
})
</script>

図12 「computed-prop3/src/App.vue」ファイルのコード

<template>
  <div>
    <h2>computedの代わりに関数で定義する</h2>
    <input v-model="firstName" placeholder="名" />
    <input v-model="lastName" placeholder="姓" />
    <!-- 関数を実行して結果を表示 -->
    <p>フルネーム:{{ fullName() }}</p> 
</template>
<script setup>
import { ref } from 'vue'

const firstName = ref('')
const lastName = ref('')
// 関数でフルネームを返す
function fullName() {
  return ${firstName.value} ${lastName.value}
}
</script>

図13 「computed-prop4/src/App.vue」ファイルのコード

<template>
  <div>
    <h2>算出プロパティと関数の更新タイミング</h2>
    <input v-model="msg" placeholder="メッセージ" />
    <p>メッセージ:{{ msg }}</p>
    <p>日時(算出プロパティ):{{ getDate_prop }}</p>
    <p>日時(関数):{{ getDate_func() }}</p>
  </div>
</template>
<script setup>
import { ref, computed} from 'vue'

const msg = ref('')
// 算出プロパティは依存するデータが変わったときだけ再評価される
const getDate_prop = computed(() => {
  // var msgVal = msg.value
  return new Date().toLocaleString()
})
// 関数は呼び出されるたびに実行される
function getDate_func() {
  return new Date().toLocaleString()
}
</script>

図17 「reiwa1/src/App.vue」ファイルのコード

<template>
  <div>
    <h2>令和 ⇄ 西暦 相互変換</h2>
    <div>
      <label>令和:</label>
      <input type="number" v-model.number="reiwa" placeholder="例:5" /> 
    </div>
    <div>
      <label>西暦:</label>
      <input type="number" v-model.number="seireki" placeholder="例:2023" />
    </div>
  </div>
</template>
<script setup>
import { ref, computed } from 'vue'

// 算出プロパティの実体となる内部の値
const reiwaValue = ref(null)
const seirekiValue = ref(null)
// 算出プロパティreiwa
const reiwa = computed({
  get() {
    return reiwaValue.value
  },
  set(value) {
    reiwaValue.value = value
    if (value > 0) {
      seirekiValue.value = 2018 + value
    } else {
      seirekiValue.value = null
    }
  }
})
// 算出プロパティseireki
const seireki = computed({
  get() {
    return seirekiValue.value
  },
  set(value) {
    seirekiValue.value = value
    if (value >= 2019) {
      reiwaValue.value = value - 2018
    } else {
      reiwaValue.value = null
    }
  }
})
</script>