讓我們先了解為什麼 AJAX 存在,這樣才能讓你在專案裡運用得更漂亮,首先,當我們拜訪一個網站的時候發生了什麼事?一個網頁從伺服器拿到資料後重新渲染畫面,但是當你想要看到新的資訊就必須再重新更新一次網頁,或點擊別的路徑。
這是“同步”
新的資料會被呈現出來當一個新的網頁對伺服器發出請求,如果你不想要重新載入這一頁呢?又如果你想要從隨時從後段拿資料可以讓你可以在現在的網頁做部分更新呢?這就是 AJAX 存在的意義。
AJAX 代表的是 Asynchronous Javascript & XML.
請記住帶入 AJAX 會使你的 app 更複雜
AJAX 有兩個部分。
“request” 這是你用 Javascript 從網頁發出的,“response” 是你從rails app 控制的。
你可以用 Javascript 做出 AJAX request。但是那需要一堆的程式碼,所以我們通常都會透過 Javascript library 來做像是 JQuery ,以下是 jQuery request 的樣子
$.get( "/vegetables", function(data) {
alert("Vegetables are good for you!");
});
然而從 rails 5.1 裡 jQuery 已經不是在預設裡了( 但你自己也可以再加回來 )
注意:會有 InvalidAuthenticityToken 錯誤如果你使用 jQuery POST 請求,意思就是說你需要傳送 csrf-token。 Rails.ajax 會自動幫你做好。
這裡有一個解決方法!
Rails 包含了自己的 AJAX 方法:
Rails.ajax({
url: "/books",
type: "get",
data: "",
success: function(data) {},
error: function(data) {}
})
記住,這個還只是從網頁發出的請求而已。
在 rails 裡,這個 AJAX 的功能是由一個叫做 Unobtrusive JavaScript 或稱作 UJS 提供的。
如果你只想用 AJAX 拿到的資料來更新網頁的其中一部分,你只有兩個選擇。你可以寫一個 Javascript 加上 erb view 來更新元素。或者你可以回傳一個 JSON 的 response,然後用 Javascript 來更新元素。
在這裡有第三個選項,這個涉及到資料為 JSON 然後產生一個 HTML 搭配
Javascript
Javascript view 的例子:
Rails.$('.random-number')[0].innerHTML = ("<%= j (render partial: 'random') %>")
j is an alias for escape_javascript
jQuery 的例子:
$('.random-number').html("<%= j (render partial: 'random') %>")
html & innerHTML 都會替換目標元素的內容。你也可以使用 append (jQuery) 語法插入新的元素而不用替換所有內容。
在一個檔案額外增加 .js.erb 副檔名然後把檔案放在 view 的資料夾,在 controller 你也在其他的 view 渲染出這一個畫面。當你呼叫一個 AJAX
後,這個 Javascript 程式碼就會自己跑起來也會更新 html。
來看看第二個選項
這裡是 controller 的程式碼:
render json: { html: render_to_string(partial: 'random') }
然後是你的 Javascript 程式碼:
Rails.ajax({
url: "/books",
type: "get",
success: function(data) { Rails.$(".random-number")[0].innerHTML = data.html; }
})
如果你想要用 AJAX 送出一張表單,你不用寫 AJAX request 就能做到,rails 可以幫助你做到這件事,那 rails 是怎麼做到的呢?
可以在 form_for 裡運用remote: true
例如:
<%= form_for @fruit, remote: true do |f| %>
<%= f.label :name, 'Fruit' %>
<%= f.text_field :name %>
<%= f.submit 'Create' %>
<% end %>
現在當你按下送出, rails 會幫你送出一個 AJAX request 而且頁面不會重新載入,如果你想要顯示 validation 錯誤你就必須要建立跟渲染一個
Javascript view (.js.erb 檔案),這個檔案可以用新的錯誤替換舊的錯誤。
這個 remote 選項也可以使用 link,所以你可以發出 AJAX delete 請求。
例如:
<%= link_to "Delete", book_path(book), { method: "delete", remote: true, data: { confirm: "Are you sure?" } }
你也可以用 Javascript view 控制這個 response
如果你想要控制 HTML requests & AJAX request 你就必須使用一些方法像是 respond_to,例如:
respond_to do |f|
f.html { redirect_to :index }
f.js
end
這個例子是讓 Turbolinks 去做或許比較簡單,你仍然可以從 controller 做到 AJAX requests & redirect_to ,讓 Turbolinks 去替換網頁的內容而不用替換整個頁面。