動作環境
Ruby 2.6.5
Rails 6.0.3.2
JavaScriptにおけるpreventDefaultがどういった働きをしているかをようやく理解することができたので、整理するために投稿してみました。
preventDefaultの意味
preventDefaultの必要性について話していく前に、そもそもpreventDefaultが何をしているのかを説明します。
###default(デフォルト)の挙動をprevent(妨害)しています。
説明になっていないと思うかもしれませんが、厳密な説明をしようとすると、おそらくかなり長い行数が必要となってしまいますし、具体的な例を提示した方がわかりやすいと思い、端的に説明しました。早速、具体的な例を元に説明していきます。
preventDefaultの具体例
<%= form_with url: "/posts", method: :post do |form| %>
<%= form.text_field :fuga %>
<%= form.submit '投稿する' , id: "submit" %>
<% end %>
index.rbにて投稿するボタンをクリックすると、fugaに入力した内容が投稿されるとします。
このままだと、投稿するボタンをクリックすると、ページの読み込みが始まってしまうので、下記のJavaScriptを記載することで非同期通信にしたとします。
function hoge() {
const submit = document.getElementById("submit");
submit.addEventListener("click", (e) => {
// 投稿するボタンをクリックした時と同じ挙動のコード(長くなってしまうので、省略)
});
};
window.addEventListener("load", hoge);
しかし、ここで1つ問題が生じてしまいます。それは、非同期通信にしたことによって同じ挙動が追加で行われてしまうので、1回の投稿で2回分投稿したことになってしまうということです。
具体的に説明すると、投稿するボタンをクリックすることで非同期通信が行われ、ページの読み込みなしで投稿が1つ増え、ページの再読み込みをすることで、本来の投稿するボタンをクリックした時の挙動が反映されて、投稿が1つ増えます。そのため、結果として同じ投稿が2回されるということが起きてしまいます。
この問題を解決するためにprevent.Defaultを使います。以下のように1行追加するだけです。
function hoge() {
const submit = document.getElementById("submit");
submit.addEventListener("click", (e) => {
e.preventDefault();
// 投稿するボタンをクリックした時と同じ挙動のコード(長くなってしまうので、省略)
});
};
window.addEventListener("load", hoge);
これによって、デフォルトの挙動を妨害することができるので、1回の投稿で2回分投稿することがなくなりました。
しかし、ここで私は「そもそもデフォルトの挙動って何?」「なぜ都合よく非同期通信だけの挙動が妨害されていないの?」
といった疑問を抱いておりました。
デフォルトの挙動とは?
基本的にRuby on Railsでのデフォルトの挙動は、ビューでの操作によって、ビューからコントローラーに情報が送られ、コントローラー内のいずれかのアクションが動くという認識で問題ないようです。
今回でいうと、投稿するボタンをクリックしたことでcreateアクションが動き、fugaを保存するということがデフォルトの挙動です。通常のRuby on Railsの流れですね。
そのため私は、preventDefaultを**「通常のRuby on Railsの流れを妨害するもの」**と捉えております。