SPAの場合はformタグに任せてデータをサブミットすることは稀で、通常は自身で定義したハンドラを呼び出してAjax通信を行うことが多い。
課題
以下のように<button type="submit" @click="exec">
を使ってボタン押下時のハンドラを実行するのは危ない。
<template>
<form>
<input type="text" placeholder="username" />
<input type="text" placeholder="password" />
<button type="submit" @click="exec">submit</button>
</form>
</template>
<script>
export default {
name: 'HelloWorld',
methods: {
exec: function () {
// 本来はajax通信をする
console.log('exec')
}
}
}
</script>
上記の記述だと、テキストフィールドでEnterを押した場合に一瞬コンソールログが出力され、自画面に遷移してしまう。
参考 HTML 5.2: 4.10. Forms
参考 HTML 5.2: 3. Semantics, structure, and APIs of HTML documents
これはブラウザのimplicit submittionという仕様が関連している。
HTML仕様を読むと以下のようなことが書いてある。
- formタグ内のテキストフィールドでEnterを押すと、自動で送信されるようにすべき(Implicit submission)
- Enterを押すと、submitボタンにclick イベントが発生する
- 入力フィールドのvalidationに引っかかったらformタグからinvalidイベントが発生する
- もしvalidationに問題なかったら formタグからsubmitイベントが発生する
- 誰もsubmitイベントをキャッチしなかったらformが送信される
- formのaction属性が空だったら、ドキュメントが配置されているアドレスに送信する
解決方法
Enter押下時に自画面への遷移を防いで、なおかつ、ボタン押下時と同じふるまいにする。 そのために、Vuejsの機能を利用してsubmitイベントを黙殺して、自身が作成したハンドラを実行する。
参考 Vuejs イベント修飾子
<template>
<form @submit.prevent="exec">
<input type="text" placeholder="username" />
<input type="text" placeholder="password" />
<button type="submit">submit</button>
</form>
</template>
<script>
export default {
name: 'HelloWorld',
methods: {
exec: function () {
// 本来はajax通信をする
console.log('exec')
}
}
}
</script>
なぜsubmitにするか?
Vuejs formタグ内のテキストフィールドでEnter押下時に、メソッドを実行する - SIerだけど技術やりたいブログ https://t.co/KfQ7z70Zem
submitしないのならtype=“button”にした方が早い気がする。— うらがみ? (@backpaper0) 2017年11月6日
submitにするとHTML上でのバリデーションがかけられます。
<template>
<form>
<input type="email" placeholder="email" />
<input type="text" placeholder="password" />
<button type="button" @click="exec">submit</button>
</form>
</template>
email形式のチェックが実行されない。
<template>
<form @submit.prevent="exec">
<input type="email" placeholder="email" />
<input type="text" placeholder="password" />
<button type="submit">submit</button>
</form>
</template>
email形式のチェックが実行される。