Ruby on Rails - AJAX
Ruby on Rails - 使用 Hotwire/Turbo 的现代 AJAX
Section titled “Ruby on Rails - 使用 Hotwire/Turbo 的现代 AJAX”AJAX (Asynchronous JavaScript and XML,异步 JavaScript 和 XML) 允许 Web 页面通过在后台与服务器交换少量数据来异步更新。这意味着可以在不重新加载整个页面的情况下更新 Web 页面的部分内容,从而带来更快、响应更流畅的用户体验。
AJAX 结合了多种技术:
- HTML/XHTML 和 CSS 用于呈现。
- 文档对象模型 (DOM) 用于动态显示和交互。
- JSON 或 XML 用于数据交换(现在 JSON 更常用)。
fetchAPI 或XMLHttpRequest对象用于异步通信。- JavaScript 将这些技术结合在一起。
虽然传统的 AJAX 通常涉及编写大量 JavaScript 代码,但现代 Rails (7+) 推崇使用 Hotwire(主要是 Turbo 和 Stimulus)来以最少的自定义 JavaScript 代码实现类似效果。
Rails 如何使用 Turbo 实现异步操作
Section titled “Rails 如何使用 Turbo 实现异步操作”Turbo 是 Hotwire 套件的一部分,它通过减少 JavaScript 代码的使用,使 Rails 应用更快、更具交互性。它通过拦截链接点击和表单提交,并异步处理它们来实现此功能。
一个典型的 Turbo 增强交互流程:
- 触发: 用户点击链接或提交表单。
- 请求: Turbo 拦截该动作并向服务器发出 AJAX 请求(使用
fetch)。 - 服务器处理: Rails 控制器动作像往常一样处理请求。它不是返回一个完整的 HTML 页面,而是可以返回一个 HTML 片段或特定的 Turbo Stream 指令。
- 客户端响应处理:
- 如果返回的是完整的 HTML 页面,Turbo Drive 会智能地更新当前页面的
<body>并合并<head>,模拟一次完整的页面加载,但速度更快。 - 如果返回的是 Turbo Stream 指令,Turbo 会更新页面特定部分(例如,追加、前置、替换或移除元素),而无需进行完整的页面刷新。
这种方法通过利用服务器端渲染和约定,简化了动态界面的构建。
AJAX 示例:使用 Turbo Streams 删除项目
Section titled “AJAX 示例:使用 Turbo Streams 删除项目”我们以一个示例来说明:使用 Turbo Streams 异步删除列表中的项目。我们假设您有一个 Pony 模型的脚手架(Scaffold)(字段:name:string, profession:string)。
步骤 1:生成脚手架 (如果尚未创建)
Section titled “步骤 1:生成脚手架 (如果尚未创建)”如果您还没有,请创建一个 Pony 资源:
$ bin/rails generate scaffold Pony name:string profession:string$ bin/rails db:migrate这会创建 Pony 的模型、控制器、视图和路由。
步骤 2:更新视图 (index.html.erb)
Section titled “步骤 2:更新视图 (index.html.erb)”打开 app/views/ponies/index.html.erb。脚手架可能已经为删除 Pony 生成了一个 button_to。我们需要确保它兼容 Turbo,并且每个 Pony 项目都有一个唯一的 DOM ID。
修改显示 Pony 的循环,将每个 Pony 包裹在一个带有 DOM ID 的元素中,并更新删除按钮:<div id="ponies"> <% @ponies.each do |pony| %> <%= content_tag :div, id: dom_id(pony) do %> <%# Use dom_id for unique ID %> <%# 使用 dom_id 生成唯一的 ID %> <p> **Name:** <%= pony.name %> </p>
<p> **Profession:** <%= pony.profession %> </p>
<%= link_to "Show this pony", pony %> <%# The button_to for destroy usually comes with data-turbo-confirm %> <%# Ensure method: :delete and data attributes are present %> <%# 用于删除的 button_to 通常自带 data-turbo-confirm %> <%# 确保 method: :delete 和 data 属性存在 %> <%= button_to "Destroy this pony", pony, method: :delete, data: { turbo_confirm: "Are you sure?" } %> <hr> <% end %> <% end %></div>
<%= link_to "New pony", new_pony_path %>dom_id(pony) 辅助方法(例如,输出 pony_123)对于 Turbo Streams 定位正确元素至关重要。
步骤 3:更新控制器 (ponies_controller.rb)
Section titled “步骤 3:更新控制器 (ponies_controller.rb)”修改 app/controllers/ponies_controller.rb 中的 destroy 动作以响应 Turbo Stream 请求:
# DELETE /ponies/1 or /ponies/1.jsondef destroy @pony = Pony.find(params[:id]) @pony.destroy
respond_to do |format| format.html { redirect_to ponies_url, notice: "Pony was successfully destroyed." } format.json { head :no_content } format.turbo_stream # Add this line to respond to Turbo Stream requests # 添加这一行以响应 Turbo Stream 请求 endend通过添加 format.turbo_stream,当请求格式是 turbo_stream 时,Rails 将查找 destroy.turbo_stream.erb 文件。
步骤 4:创建 Turbo Stream 视图 (destroy.turbo_stream.erb)
Section titled “步骤 4:创建 Turbo Stream 视图 (destroy.turbo_stream.erb)”创建一个新文件 app/views/ponies/destroy.turbo_stream.erb,内容如下:
<%= turbo_stream.remove @pony %><%# Or equivalently: turbo_stream.remove dom_id(@pony) %><%# 或等效地:turbo_stream.remove dom_id(@pony) %>此模板告诉 Turbo 找到一个具有与 @pony 对象对应的 DOM ID(例如,id="pony_123")的 HTML 元素,并将其从页面中移除。
步骤 5:测试应用
Section titled “步骤 5:测试应用”- 启动 Rails 服务器:
$ bin/rails server - 打开浏览器并访问
http://localhost:3000/ponies。 - 如果您没有任何 Pony,点击“New pony”,填写详细信息(例如,Name: “Rainbow Dash”, Profession: “Weather Patrol”),然后点击“Create Pony”。您将被重定向到 Pony 的 show 页面。返回 Pony 列表 (
/ponies)。 - 您应该在列表中看到您创建的 Pony。每个 Pony 条目将包含其名称、职业、“Show this pony”链接和“Destroy this pony”按钮。
现在,点击其中一个 Pony 的“Destroy this pony”按钮。
由于 data: { turbo_confirm: "Are you sure?" },您应该会看到一个确认对话框(例如,“Are you sure?”)。
点击“OK”。该 Pony 项目将从列表中消失,但页面不会完全重新加载。URL 将保持为 /ponies。这就是 Turbo Streams 的实际效果!
此示例展示了一种简单而强大的方法,使用 Hotwire/Turbo 增强 Rails 中的用户界面,通常可以替代需要更多自定义 JavaScript 的旧式 AJAX 模式。