龙空技术网

使用 Hotwire 构建响应式 Rails 应用程序

墨谈科技 64

前言:

此刻朋友们对“railsajax提交表单”大约比较讲究,大家都需要学习一些“railsajax提交表单”的相关资讯。那么小编同时在网络上搜集了一些对于“railsajax提交表单””的相关知识,希望小伙伴们能喜欢,朋友们快快来了解一下吧!

每日分享最新,最流行的软件开发知识与最新行业趋势,希望大家能够一键三连,多多支持,跪求关注,点赞,留言。如果您正在使用 Ruby on Rails 开发现代单页应用程序,您很可能会使用一些花哨的 JS 框架来很好地更新您的 UI,而无需重新加载页面。如果不使用它们,您将无能为力;这些天来这是一种标准......直到Rails得到了Hotwire。

使用 Hotwire,您无需编写大量 Javascript 即可获得快速且响应迅速的 Web 应用程序。嗯,听起来不错,但 Hotwire 是什么?在本文中,我们将介绍 Hotwire 的基础知识并使用它构建一个示例应用程序。

响应式 Rails 应用程序有哪些选项?
2013 年 6 月 25 日,Rails 4 发布,引入了 Turbolinks。Turbolinks 为 Rails 的“响应能力”做了什么?Turbolinks 拦截所有链接点击,而不是发送常规GET请求,而是发送异步 Javascript 请求 (AJAX) 以获取 HTML。然后它合并head获取页面的标签并替换页面的整个body标签,因此不会重新加载整个页面。无需重新加载样式表或脚本,这意味着更快的页面导航。但它仍然在替换整个body页面,而不仅仅是更改页面的某些部分。

但是,如果您只想重新加载已更改的部分怎么办?当您将某些元素标记为 时,您可以使用 Rails AJAX 助手data-remote='true',这使得这些元素发送 AJAXGET/POST请求而不是常规GET/POST请求。Rails 以生成的 JS 代码进行响应,然后由浏览器执行以动态更新页面的这些部分。

然后我们可以在前端使用一些 JS 组件(例如,使用 React),以使应用程序感觉更加响应。所以,JS 组件发送一个 AJAX 请求,Rails 服务器用 JSON 数据响应它。然后前端框架将接收到的 JSON 转换为 DOM 元素并更新 DOM 以反映这些变化。而且效果很好;唯一的缺点是它在页面上混合了服务器端渲染和客户端渲染。

如今,另一种更传统的方式是全力以赴并在前端使用 React、Vue 或其他 JS 框架来仅使用客户端渲染,即所谓的单页应用程序 (SPA)。使用这种方法,前端是一个单独的应用程序,它将 AJAX 请求发送到 Rails 服务器,而 Rails 只是一个 JSON API。您可能知道,构建、维护和部署两个具有可互换数据的独立应用程序非常复杂。

但是,如果您可以构建一个 SPA,而不需要构建两个单独的应用程序和编写大量 Javascript 代码的复杂性呢?以下是 Hotwire 可以为您提供的帮助。

什么是Hotwire?
Hotwire 是构建类似 SPA 的 Web 应用程序的另一种方法,它使用 Rails 模板呈现所有 HTML 服务器端,同时保持应用程序的快速响应。在服务器端保持渲染使您的开发体验更简单、更高效。Hotwire 名称基本上是“HTML Over the Wire”的缩写,意思是从服务器向客户端发送生成的 HTML 而不是 JSON。它也不需要您编写太多自定义 javascript 代码。Hotwire 由 Turbo 和 Stimulus 组成。

什么是Turbo gem?
Turbo gem 是 Hotwire 的核心。它是一组动态更新页面的技术,通过将页面划分为可以利用 WebSockets 作为传输进行部分更新的组件来加速导航和表单提交。如果您曾经在 Rails 中使用过 WebSockets,那么您很可能知道 Rails 使用 ActionCable 来处理 WebSockets 连接,并且它默认包含在 Rails 中。Turbo gem 由 Turbo Drive、Turbo Frames 和 Turbo Streams 组成。

Turbo Drive
Turbo Drive 用于拦截链接点击(就像 Turbolinks 之前所做的那样)并拦截表单提交。Turbo Drive 然后合并页面的 head 标签并替换页面的 body 标签。在与 Turbolinks 相同的情况下,不会重新加载整个页面,这对于某些页面可能会很快,但响应速度不如 2022 应用程序预期的那样,因此您可能会考虑仅更新页面的某些部分,而不是整个页面. 这就是 Turboframes 派上用场的地方。

Turbo Frame
您可以通过简单地将页面的一部分包装在turbo-frame具有唯一 id 的标签中来简单地使页面的一部分成为 Turbo Frame。

<turbo-frame id="13">
...
</turbo-frame>



这使得框架内的任何交互都局限于该框架。该框架内的任何交互都会向 Rails 服务器发送一个 AJAX 请求,并且服务器只响应该框架的 HTML,这允许 Turbo 仅自动替换页面上的该框架。这不需要编写任何 Javascript。

但是,如果您想同时更新页面的多个部分怎么办?这就是 Turbo Streams 可以为您提供的帮助。
turbo-stream
当用户与页面上的元素(例如,表单/链接)交互并且 Turbo Drive 向服务器发送 AJAX 请求时,服务器会以包含 Turbo Stream 元素的 HTML 进行响应。这些就像是 Turbo 为了更新页面的受影响部分而遵循的指示。Turbo Streams 包括七个可用的操作append, prepend, (insert) before, (insert) after, replace, update, and remove:

<turbo-stream action="append" target="target_a">
<template>
HTML
</template>
</turbo-stream>

<turbo-stream action="prepend" target="target_b">
<template>
HTML
</template>
</turbo-stream>

<turbo-stream action="replace" target="target_c">
<template>
HTML
</template>
</turbo-stream>



Turbo Streams 使用 ActionCable 通过 WebSocket 异步向多个客户端提供更新。同样,您无需编写任何 Javascript 代码即可获得所有这些。但是,即使您出于任何原因需要一些自定义 Javascript(例如,一些动画、日期选择器等),Hotwire 也可以通过 Stimulus 为您提供帮助。

什么是Stimulus?
与具有带有动作的控制器的 Rails 一样,Stimulus 允许您类似地组织客户端代码。你有一个控制器,它是一个 Javascript 对象,它定义了动作,即 Javascript 函数。然后使用 HTML 属性将控制器操作连接到页面上的交互式元素。然后在触发 DOM 事件时运行该操作以响应。

让我们用 Hotwire 创建一个示例 Rails 应用程序
阅读完以上所有内容后,您可能想知道我是如何使用它的。Hotwire 使用起来非常简单;我们只需要一个标准的 Rails 应用程序和一个 Redis 服务器。

首先,您需要安装 Ruby 3 和 Rails 7 以及 Redis 服务器,我不会介绍它们的安装过程,但是您可以根据您的平台轻松找到所需的任何说明。

所以,让我们设置一个新的 Rails 应用程序(我们将使用 Bootstrap 作为 CSS 选项,只是为了让我们的应用程序看起来更好一点):

1

rails new bookstore --css bootstrap



在 Rails 生成所有需要的文件后, cd 进入 app 目录:

cd bookstore



Rails 7 初始应用程序拥有我们开始使用 Hotwire 所需的一切;Gemfile 包括 Redis gem、Turbo-rails gem 和 Stimulus-rails。

确保您已启动并运行 Redis 服务器。Redis 是必需的,因为 ActionCable 使用它来存储与 WebSockets 相关的信息。

Rails 连接 Redis 服务器的默认地址和端口设置在config/cable.yml

development:
adapter: redis
url: redis://localhost:6379/1



然后我们可以生成我们的模型、控制器和迁移,在我们的 Bookstore 示例中它们将是“Books”。它将有一个字符串标题,文本类型的描述,并且喜欢计数器作为整数:

1

rails g scaffold books title:string description:text likes:integer


让我们修复生成的迁移,以便我们添加到数据库中的任何书默认为 0 个赞:

class CreateBooks < ActiveRecord::Migration[7.0]
def change
create_table :books do |t|
t.string :title
t.text :description
t.integer :likes, default: 0
t.timestamps
end
end
end


不要忘记为我们的应用程序创建一个数据库并在终端中运行它:

rake db:create db:migrate



让我们将书籍列表页面设置为应用程序的根页面,打开config/routes.rb,并添加缺少的根声明:

Rails.application.routes.draw do
root 'books#index'
resources :books
end



然后你应该能够在终端中使用rails server命令或./bin/dev(它也将观察 CSS 和 js 的变化)运行 rails server,当你在浏览器中访问这个页面时,你应该会看到如下内容:



让我们将 Book 部分更改为app/views/books/_book.html.erb:

Rails.application.routes.draw do
root 'books#index'
resources :books
end



turbo_stream_from告诉 Hotwire 使用 WebSocket 更新用标识的帧:book_id,并turbo_frame_tag标识可以在更新时用部分替换的帧。

为了告诉 Turbo 我们想要将每本新创建的图书添加到图书列表的开头并在每次点击赞按钮时更新赞数,我们需要将以下回调添加到app/models/book.rb文件中(还要添加验证):
class Book < ApplicationRecord
after_create_commit { broadcast_prepend_to :books }
after_update_commit { broadcast_replace_to "book_#{id}" }
validates :title, :description, presence: true
end


第一个告诉 Turbo 在创建时使用 :books Turbo Stream 进行更新,第二个告诉使用:book_id用更新替换部分。

然后让我们在 book 控制器中修复排序,并在以下位置添加新的 book 变量赋值(这样我们就可以从根路径创建一本书)app/controllers/books_controller.rb:

...
def index
@books = Book.order(created_at: :desc)
@book = Book.new
end
...


我们还应该编辑app/views/books/index.html.erb以添加我们的 Turbo Streams 和 Turbo Frames:

<h1>Books</h1>
<%= turbo_stream_from :books %>

<%= turbo_frame_tag :book_form do %>
<%= render 'books/form', book: @book %>
<% end %>

<%= turbo_frame_tag :books do %>
<%= render @books %>
<% end %>



为了避免在我们创建新书或更新现有书并停留在同一主页时出现重定向,我们还需要在以下位置编辑、创建和更新操作app/controllers/books_controller.rb:

...
def create
@book = Book.new(book_params)

respond_to do |format|
if @book.save
format.html { redirect_to root_path }
else
format.turbo_stream { render turbo_stream: turbo_stream.replace(@book, partial: 'books/form', locals: { book: @book }) }
format.html { render :new, status: :unprocessable_entity }
end
end
end

def update
respond_to do |format|
if @book.update(book_params)
format.html { redirect_to root_path }
else
format.html { render :edit, status: :unprocessable_entity }
end
end
end


此时,我们的书店应用应如下所示:


每当您使用主页上的表单创建新书时,Turbo 都会将其添加到图书列表中,而无需重新加载页面。如果您在浏览器中打开多个选项卡 - 它会更新所有选项卡。“喜欢”按钮也可以在不重新加载页面的情况下工作,并在所有标签中更新书籍的喜欢计数。所有这一切都没有一行 Javascript 代码。多么酷啊?

这个示例应用程序是一个基本示例,说明了您可以在 Rails 中使用 Hotwire 做什么,但您可以使用 Turbo 和 Stimulus 做更复杂的事情。

所以如果你想用 Rails 开始一个新的 SPA,如果你需要 React、Vue 或任何其他前端框架,请三思而后行;尝试一下 Hotwire 可能会更有成效。很有可能它会让你开心。

标签: #railsajax提交表单