Vディレクティブとは、テンプレート(HTML)内で動的な仕組みを要素に与えるための属性です。v-で始まる属性により、Vueのテンプレート構文内で特別な動作を定義するために使われます。
v-modelディレクティブは、テンプレート構文で双方向バインディングを実現するためのディレクティブで、input, textarea, selectなどのフォーム入力の値が変更されるとデータも自動で更新(逆も同じ)、ref() や reactive() を使ってリアクティブな状態を作成します。それでは簡単なテンプレートを書いてバインドする状態を確認していきます。
<template>
<input v-model="name" /> // 値nameがバインド状態
<p>こんにちは、{{ name }} さん</p>
</template>
<script setup>
import { ref } from 'vue'
const name = ref('アシリ') // リアクティブな状態、初期値にアシリが
</script>
<template>
<div>
<!-- .lazy:changeイベント時に更新 -->
<input v-model.lazy="message" />
<!-- .number:数値として扱う -->
<input v-model.number="age" type="number" />
<!-- .trim:空白を除去 -->
<input v-model.trim="name" />
</div>
</template>
<script setup>
import { ref } from 'vue'
const message = ref('')
const age = ref(0)
const name = ref('')
</script>
v-modelディレクティブが最もよく使われるのは、やはりフォームの値とデータが自動的に同期する便利機能より、フォームを構築する際によく使われます。下記にv-modelを使った基本的なフォームテンプレートを紹介致します。html/CSSでゴリゴリ書くは同じですが(ちなみに私はTailwindCSSで楽はしませんゴリゴリが好きです)、phpやJSでお問い合わせフォームを構築したことがある方なら、フレームワークによりこれだけ?と思うくらいシンプルです。
<template>
<form @submit.prevent="submitForm">
<div>
<label>名前:</label>
<input type="text" v-model="form.name" />
</div>
<div>
<label>メールアドレス:</label>
<input type="email" v-model="form.email" />
</div>
<div>
<label>性別:</label>
<label><input type="radio" value="男性" v-model="form.gender" /> 男性</label>
<label><input type="radio" value="女性" v-model="form.gender" /> 女性</label>
</div>
<div>
<label>出身地:</label>
<select v-model="form.region">
<option disabled value="">選択してください</option>
<option>北海道</option>
<option>東京</option>
<option>大阪</option>
<option>福岡</option>
</select>
</div>
<div>
<label>自己紹介:</label>
<textarea v-model="form.intro" rows="3" />
</div>
<button type="submit">送信</button>
</form>
</template>
<script setup>
import { reactive } from 'vue'
const form = reactive({
name: '',
email: '',
gender: '',
region: '',
intro: ''
})
const submitForm = () => {
// フォーム送信処理(API)
}
</script>
フォームなど、何らかの情報をVue(フロントエンド)からサーバー(バックエンド)にデータ通信をする時、セキュリティ上の欠陥より脅威にさらされるのを防ぐために、フロント・バックエンドと共にスクリプトインジェクション対策等必ずしましょう。安全なフォームを作ることで、ユーザーだけでなく、サービス全体の信頼性を守ることができます。
例えば以下のような入力がそのまま通信されると危険
<script>alert('XSS!')</script>
これだけでv-html で表示された場合、スクリプトが実行されます。これがよく聞く XSS(クロスサイトスクリプティング)攻撃ですね。
※マスタッシュ内{{}}であれば自動エスケープしてくれますが、v-htmlを使う場合やサーバーへ送信する場合は自分で対策が必要です!
しかし、VueにはXSSを防ぐためのサニタイズライブラリがあります。
※フロント側で入力を制限しても、サーバーに直接悪意あるリクエストが送られる可能性があります。サーバー側でも通信対策は必須です。
HTMLの文字列を安全にするために、悪意あるスクリプトや危険なタグを自動で除去してくれる、ユーザー入力からスクリプトインジェクション(XSS)を防ぐためのサニタイズライブラリです。
Dompurifyライブラリインストール
npm install dompurify
<script setup>
import DOMPurify from 'dompurify';
const sanitize = {
name: DOMPurify.sanitize(form.name),
email: DOMPurify.sanitize(form.email),
intro: DOMPurify.sanitize(form.intro),
}
// これをAPI送信に使う
await fetch('/api/contact', { method: 'POST', body: JSON.stringify(sanitize) })
</script>
DOMPurify.sanitize() を使うことで、ユーザー入力から悪意あるスクリプトを除去します。バリデーション、エラーメッセージの表示など対応してサービス全体の信頼性を守る対策を心がけましょう。
いかがでしたでしょうか。今回は、JavaScriptフレームワークVueのリアクティブv-modelについて、ご紹介させていただきました。v-modelはフォーム入力とその双方向バインディングで特に利用されるAPI通信には欠かせないリアクティブですね。フレームワークにより作業の効率が上がりましたが、Webサイトやアプリの脆弱性を悪用して、ユーザーに不正なスクリプトを実行されるXSS対策など危険もまた隣合わせですので、上流からしっかり実装前の設計段階で考えておくとよいかと思います。
以上となります。できる限りわかりやすく伝えようとしても書くのは難しいです。
コードや記事の書き方について気になるところがあれば、アドバイスいただけると嬉しいです。
要件定義からブラッシュアップ/実装運用まで一貫して担当。また内部対策を中心に、GTM・GA4・Looker Studioと分析・改善案の策定も進めています。北緯43度マルチエンジニア