发布于 2026-01-06 1 阅读
0

使用 Ruby on Rails、CableReady、Mrujs、Stimulus 和 Tailwind 的服务器端渲染模态表单 DEV 的全球展示与讲述挑战赛,由 Mux 呈现:展示你的项目!

使用 Ruby on Rails、CableReady、Mrujs、Stimulus 和 Tailwind 实现服务器端渲染的模态表单

由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!

Rails 生态系统持续蓬勃发展,Rails 开发人员拥有构建现代化、响应式、可扩展 Web 应用程序所需的一切工具,能够快速高效地完成任务。如果您重视提供卓越的用户体验,那么在 Rails 领域,您的选择从未如此丰富。

今天我们将深入了解这个生态系统,并使用两个前沿的 Rails 项目,使用户能够提交在模态框内渲染的表单。

表单将在模态框中打开,内容由服务器动态填充,服务器将处理表单提交,DOM 将更新而无需整个页面翻转。

为了实现这一目标,我们将使用Stimulus进行前端交互,使用CableReady全新的CableCar 功能从服务器发送内容,并使用Mrujs启用 AJAX 请求并自动处理 CableCar 的操作。

会非常精致。

完成后,我们的应用程序将如下所示:

一段屏幕录像显示一个初始为空白的网页,网页顶部标题为“客户”,并包含一个创建新客户的链接。用户点击该链接后,屏幕上会弹出一个模态窗口。用户输入姓名创建客户,页面会自动更新显示新客户的信息。用户继续添加和更新多个客户记录,每次表单都会以模态窗口的形式打开,页面也会立即更新显示用户的更改。

本文包含相当多的 JavaScript 代码,并假定读者对 Ruby on Rails 的基础知识有扎实的了解。

如果您之前从未使用过 Rails,本文的节奏可能对您来说有点快。虽然您需要熟悉 Rails 和 JavaScript,但您无需事先了解 CableReady 或 Stimulus。

和往常一样,您可以在Github上找到本文的完整源代码

让我们开始吧!

设置

如果您想跳过设置步骤直接开始编码,您可以克隆此存储库的主分支,然后向下滚动到“客户布局”部分。

为了完成所有安装,我们将冒险使用新发布的、仍处于 alpha 测试阶段的jsbundling-railscssbundling-rails gems。

首先,我们将创建一个 Rails 应用程序,并使用 alpha js/cssbundling gems 从终端安装 Webpack 和 Tailwind:

rails new tiny_crm --skip-webpack-install --skip-javascript
cd tiny_crm
bundle add jsbundling-rails cssbundling-rails
rails javascript:install:webpack
rails css:install:tailwind
bin/dev
Enter fullscreen mode Exit fullscreen mode

请注意,这些 gems 非常新,如果您遇到错误,请检查文档以查看命令是否已更改,或者联系我并告诉我您遇到的错误。

安装好 Webpack 和 Tailwind 之后,接下来我们将从终端安装本指南的核心依赖项:Stimulus、CableReady(以及 Action Cable)和 Mrujs:

bundle add hotwire-rails
be rails hotwire:install
Enter fullscreen mode Exit fullscreen mode

然后更新你的 Gemfile 文件,引入最新的 cable_ready 库。

gem "cable_ready", github: "stimulusreflex/cable_ready"
Enter fullscreen mode Exit fullscreen mode

请注意,如果您将来阅读此内容,本指南使用的是 5.0 版本。

然后从您的终端执行:

bundle
yarn add mrujs cable_ready @rails/actioncable
Enter fullscreen mode Exit fullscreen mode

接下来,app/javascript/packs/application.js像这样进行更新,以引入新的依赖项并配置 Mrujs 以使用其CableCar 插件

import "./controllers"
import mrujs from "mrujs";
import CableReady from "cable_ready"
import { CableCar } from "mrujs/plugins"
import * as Turbo from "@hotwired/turbo"

window.Turbo = Turbo;

mrujs.start({
  plugins: [
    new CableCar(CableReady)
  ]
})
Enter fullscreen mode Exit fullscreen mode

需要设置的依赖项太多了。我们真的需要这么多东西才能显示一个模态框吗?不,真的没必要。

本文中使用的技术只需要 Action Cable(一个核心 Rails 库)、CableReady 和 Mrujs。

要按照本指南一步一步操作,需要用到 Tailwind 和 Stimulus,但我们只是用它们来实现一些可以用您自己的 CSS 和原生 JavaScript 实现的功能(如果您更喜欢后者的话)。

最终,你唯一需要的 UI 组件就是一个可以打开和关闭的模态框。Stimulus 和 Tailwind 是实现这一目标的简单方法,但它们并非唯一方法!

接下来,为了完成复制/粘贴的设置工作,我们将在此应用程序中创建和编辑客户,所以让我们先搭建这个资源框架:

rails g scaffold Customer name:string
rails db:migrate
Enter fullscreen mode Exit fullscreen mode

设置完成!目前为止一切顺利。现在我们可以开始编写代码了。

客户布局

首先,我们将对客户首页应用一些基本样式:

<div class="max-w-3xl mx-auto mt-8">
  <div data-controller="modal" class="flex justify-between items-baseline mb-6">
    <h1 class="text-3xl text-gray-900">Customers</h1>
    <%= link_to 'New Customer', new_customer_path, class: "text-blue-600", data: { action: "click->modal#open" } %>
    <%= render 'modal' %>
  </div>
  <div id="customers" class="flex flex-col items-baseline space-y-6 p-4 shadow-lg rounded">
    <% @customers.each do |customer| %>
      <%= render "customer", customer: customer %>
    <% end %>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

索引视图会显示客户列表,以及包含创建新客户链接的标题。

头部容器 div 包含一个controller="modal"数据属性,该属性引用了一个尚不存在的 Stimulus 控制器。同样,新客户链接的属性modal中也引用了同一个控制器data-action

我们很快就会创建那个控制器,不过现在,点击新客户链接会将浏览器导航到……customers/new

索引视图还会渲染两个尚不存在的局部视图modalcustomer接下来,让我们创建并填充它们,以便我们可以再次渲染索引页面。

首先,客户部分:

touch app/views/customers/_customer.html.erb
Enter fullscreen mode Exit fullscreen mode

目前,客户部分视图仅渲染客户姓名:

<div class="text-gray-700 border-b border-gray-200 w-full pb-2">
  <%= customer.name %>
</div>
Enter fullscreen mode Exit fullscreen mode

接下来创建模态框局部视图:

touch app/views/customers/_modal.html.erb
Enter fullscreen mode Exit fullscreen mode

请填写以下内容:

<div data-modal-target="container"
     class="hidden fixed inset-0 overflow-y-auto flex items-center justify-center"
     style="z-index: 9999;">
  <div class="max-w-lg max-h-screen w-full relative">
    <div class="m-1 bg-white rounded shadow">
      <div class="px-4 py-5 border-b border-gray-200 sm:px-6">
        <h3 class="text-lg leading-6 font-medium text-gray-900">
          Customer
        </h3>
      </div>
      <form id="customer_form"></form>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

这里重要的元素是modal-target="container"数据属性(Stimulus 控制器将使用该属性来打开/关闭模态框)和空<form>元素。

当用户打开模态框时,此表单元素最终会填充来自服务器的内容。

索引标记就位,服务器通过运行bin/dev,前往http://localhost:3000/customers,确保一切显示正常。

接下来我们将创建modalStimulus 控制器,并用服务器渲染的内容填充它。我也很兴奋。

显示新客户模态框

首先,我们需要使用便捷的生成器创建一个新的刺激控制器。在您的终端中:

rails g stimulus modal
Enter fullscreen mode Exit fullscreen mode

并在控制器中填写以下内容:

// Credit: This controller is an edited-to-the-essentials version
// of the modal component created by @excid3 as part of the essential 
// tailwind-stimulus-components package found here:
// https://github.com/excid3/tailwindcss-stimulus-components

// In production, use the full component from the 
// library or expand this controller to allow for 
// keyboard closing and dealing with scroll positions

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static targets = ['container'];

  connect() {
    this.toggleClass = 'hidden';
    this.backgroundId = 'modal-background';
    this.backgroundHtml = this._backgroundHTML();
    this.allowBackgroundClose = true;
  }

  disconnect() {
    this.close();
  }

  open() {
    document.body.classList.add('fixed', 'inset-x-0', 'overflow-hidden');
    this.containerTarget.classList.remove(this.toggleClass);
    document.body.insertAdjacentHTML('beforeend', this.backgroundHtml);
    this.background = document.querySelector(`#${this.backgroundId}`);
  }

  close() {
    if (typeof event !== 'undefined') {
      event.preventDefault()
    }
    this.containerTarget.classList.add(this.toggleClass);
    if (this.background) { this.background.remove() }
  }

  _backgroundHTML() {
    return `<div id="${this.backgroundId}" class="fixed top-0 left-0 w-full h-full" style="background-color: rgba(0, 0, 0, 0.7); z-index: 9998;"></div>`;
  }
}
Enter fullscreen mode Exit fullscreen mode

这里有很多 JavaScript 代码,但它并没有执行任何太复杂的操作。

在 中connect,我们设置控制器运行所需的默认值。

open只是简单地将类应用于 body 和模态容器,使模态框在屏幕上可见,并将标准的灰色背景应用于页面的其余部分。

调用该函数时close,背景将被移除,模态框将被隐藏。

如果您决定在实际项目中使用这种方法,请考虑使用本代码所基于的Stimulus 组件。以上代码为了简洁而进行了编辑,但这些编辑会引入一些滚动和辅助功能方面的问题,而完整的组件可以很好地处理这些问题。

刺激控制器创建完毕,我们几乎可以渲染模态框了。在继续之前,让我们先退一步,确保我们清楚自己想要实现什么目标。

我们的目标是创建一个服务器端渲染的模态框,允许用户创建新客户。模态框中的表单提交后,新创建的客户应添加到客户列表中,并且模态框应关闭。

首要任务是打开模态框并显示来自服务器的内容,这意味着当用户点击首页上的“新客户”链接时:

  • 应向服务器发出请求,以检索客户表单的内容。
  • 内容应替换页面初始加载时模态框部分渲染的空白客户表单。
  • 模态框应该打开

这比听起来要容易得多。

我们将使用 Mrujs 向目标服务器发出 AJAX 请求customers#new,我们将使用 CableCar 对操作进行排队,Mrujs 将自动为我们处理这些操作。

首先,我们需要告诉 Mrujs 将新客户链接转换为支持 CableCar 的链接。

如文档所述,我们将通过更新首页上的链接来实现这一点,如下所示:

<%= link_to 'New Customer', new_customer_path, class: "text-blue-600", data: { action: "click->modal#open", cable_car: "" } %>
Enter fullscreen mode Exit fullscreen mode

在这里我们添加了,剩下的就交给data-cable-car=""Mrujs来处理了

这项更改生效后,当用户点击“新客户”链接时,将向服务器发送一个 AJAX 请求customers#new

由于我们稍后将渲染表单的局部视图,现在就让我们更新该局部视图吧:

<%= form_with(model: customer, id: "customer_form") do |form| %>
  <div class="px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
    <% if customer.errors.any? %>
      <div class="p-4 border border-red-600">
        <h2>
          Could not save customer
        </h2>
        <ul>
          <% customer.errors.full_messages.each do |message| %>
            <li><%= message %></li>
          <% end %>
        </ul>
      </div>
    <% end %>

    <div class="form-group">
      <%= form.label :name %>
      <%= form.text_field :name %>
    </div>

  </div>
  <div class="rounded-b mt-6 px-4 sm:grid sm:grid-cols-2 sm:gap-3 sm:grid-flow-row-dense">
    <%= form.button class: "w-full sm:col-start-2 bg-blue-600 px-4 py-2 mb-4 text-white rounded-sm hover:bg-blue-700" %>
    <button data-action="click->modal#close" class="mt-3 w-full sm:mt-0 sm:col-start-1 mb-4 bg-gray-100 hover:bg-gray-200 rounded-sm px-4 py-2">
      Cancel
    </button>
  </div>
<% end %>
Enter fullscreen mode Exit fullscreen mode

其中大部分是标准的 Tailwind 类,用于对表单应用一些简单的样式。

重要的部分是表单的 id(在第 1 行分配)和data-action分配给关闭按钮的 id,它会触发close我们modal之前在 Stimulus 控制器中定义的函数。

我们还可以使用 Tailwind 的表单插件来美化表单。这是可选的,但如果您想使用它,请先在终端中使用 yarn 安装它:

yarn add @tailwindcss/forms
Enter fullscreen mode Exit fullscreen mode

然后更新tailwind.config.js

module.exports = {
  mode: 'jit',
  purge: [
    './app/views/**/*.html.erb',
    './app/helpers/**/*.rb',
    './app/javascript/**/*.js'
  ],
  plugins: [
    require('@tailwindcss/forms')
  ]
}
Enter fullscreen mode Exit fullscreen mode

接下来,我们需要更新new方法以CustomersController渲染CableReady 操作,使用新引入的CableCar。为此,我们将对方法进行两处更改CustomersController

首先更新控制器,使其包含 CableReady::Broadcaster,以便控制器能够访问cable_car

class CustomersController < ApplicationController
  include CableReady::Broadcaster
  # snip
end
Enter fullscreen mode Exit fullscreen mode

如果您愿意,可以随意添加includeApplicationController

然后按如下方式更新CustomersController新方法:

def new
    html = render_to_string(partial: 'form', locals: { customer: Customer.new })
    render operations: cable_car
      .outer_html('#customer_form', html: html)
end
Enter fullscreen mode Exit fullscreen mode

在这里,我们将表单的部分内容渲染成一个字符串,然后将其传递给 cable_car,并在outer_html 操作中使用,目标是(当前为空的)客户表单。

完成以上步骤后,返回http://localhost:3000/customers并点击“新建客户”链接。如果一切顺利,您应该会看到模态框打开并显示客户表单。

目前为止,工作做得非常出色。

接下来,我们将使用相同的 CableCar 方法来处理表单提交。

提交表格

这一部分内容看起来应该很熟悉。首先,我们将更新客户表单,添加缆车数据属性,就像我们在上一节中添加到新客户链接中一样:

<%= form_with(model: customer, id: "customer_form", data: { cable_car: "" }) do |form| %>
Enter fullscreen mode Exit fullscreen mode

这再次告诉 Mrujs 使用 AJAX 请求提交表单,并期望 CableReady 操作作为响应执行。

接下来,返回customers_controller.rb并更新创建方法:

def create
  @customer = Customer.new(customer_params)

  if @customer.save
    html = render_to_string(partial: 'customer', locals: { customer: @customer })
    render operations: cable_car
      .append('#customers', html: html)
  else
    # TODO: Handle errors
  end
end
Enter fullscreen mode Exit fullscreen mode

这里我们再次将局部视图渲染成字符串,并将该字符串传递给一个操作(这次是 `addCustomer` append)。目标是客户索引视图中渲染的客户列表,新创建的客户将被添加到列表底部。如果您愿意,也可以使用`prepend`将客户添加到列表顶部。

设置完成后,打开模态框,输入姓名,然后提交表单。您应该会看到新创建的客户如预期添加到列表中,但模态框不会关闭。

这并非理想情况。

一段网页屏幕录像。用户点击页面上的“新客户”链接,弹出一个模态框。用户提交模态框后,创建的客户信息被添加到页面中,但模态框仍然保持打开状态。

表单提交成功后,我们如何关闭模态框?这可以通过利用 CableReady 的一些强大功能来实现——链式操作发出自定义 DOM 事件

为了实现这一点,我们首先需要在发送给 Mrujs 的操作链中添加另一个操作:

def create
    # snip
    render operations: cable_car
      .append('#customers', html: html)
      .dispatch_event(name: 'submit:success')
end
Enter fullscreen mode Exit fullscreen mode

dispatch_event 操作允许我们发出任何我们想要的事件。有了这个在成功提交时触发的新事件,关闭模态框就变得非常简单,只需向模态框的 Stimulus 控制器添加一个事件监听器,如下所示:

open() {
  document.addEventListener("submit:success", () => {
    this.close()
  }, { once: true });
  // snip
}
Enter fullscreen mode Exit fullscreen mode

当模态框打开时,会创建一个事件监听器,该监听器会针对从 cable_car 有效负载分发的事件名称进行调整。

现在,当您提交模态表单时,成功提交表单后,会同时发送`and`append和 `operations`操作,Mrujs 的魔法会自动执行这些操作,并且事件监听器会关闭模态框。dispatch_eventsubmit:success

处理错误

目前为止工作进展顺利。接下来我们将再次处理表单错误render operations

validates_presence_of :name首先,通过添加以下内容,允许客户提交的内容出现验证错误:models/customer.rb

这样一来,当表单提交时姓名为空,表单提交就会失败。此时,我们希望在模态框内渲染客户表单,并附带验证错误信息。

要在提交失败时显示错误信息,请按如下方式更新 create 方法:

def create
  @customer = Customer.new(customer_params)

  if @customer.save
    html = render_to_string(partial: 'customer', locals: { customer: @customer })
    render operations: cable_car
      .append('#customers', html: html)
      .dispatch_event(name: 'submit:success')
  else
    html = render_to_string(partial: 'form', locals: { customer: @customer })
    render operations: cable_car
      .inner_html('#customer_form', html: html), status: :unprocessable_entity
  end
end
Enter fullscreen mode Exit fullscreen mode

在这个else分支中,我们再次将局部视图渲染成字符串并执行渲染操作。这次,由于我们不希望模态框关闭,也不需要替换<form>元素本身,所以我们只需要使用一个inner_html操作即可。

打开模态框,提交一个空白表单,可以看到表单按预期重新渲染并显示错误信息。

一段网页屏幕录像。用户点击页面上的“新客户”链接,弹出一个模态框。用户未输入任何内容就提交了表单,表单随即更新并显示错误信息,提示姓名必填。

你能坚持到最后真是太棒了!接下来,我们来看看如何轻松地复用这个模态框来编辑客户信息,并对模态框的打开方式进行一些小的优化。

缆车乘客编辑

空白客户表单模态框的一个优点是,我们可以无需修改即可重复使用它来编辑现有客户,这样我们就只需要一个很小的模态框容器,就可以在页面上重复使用它来创建任意数量的模态框。

首先,cable_car在局部视图中添加一个启用模态框的链接customer

<div class="text-gray-700 border-b border-gray-200 w-full pb-2" id='<%= "customer-#{customer.id}" %>'>
  <%= link_to customer.name, edit_customer_path(customer), data: { cable_car: "", action: "click->modal#open" } %>
</div>
Enter fullscreen mode Exit fullscreen mode

在这里,我们设置了链接的相关数据属性,并在外层 div 元素中添加了一个唯一 ID。当编辑表单提交时,我们将使用该 ID 来替换客户信息的内容。

接下来,回到CustomersController调整editupdate方法的部分:

def edit
  html = render_to_string(partial: 'form', locals: { customer: @customer })
  render operations: cable_car
    .replace('#customer_form', html: html)
end

def update
  if @customer.update(customer_params)
    html = render_to_string(partial: 'customer', locals: { customer: @customer })
    render operations: cable_car
      .replace("#customer-#{@customer.id}", html: html)
      .dispatch_event(name: 'submit:success')
  else
    html = render_to_string(partial: 'form', locals: { customer: @customer })
    render operations: cable_car
      .inner_html('#customer_form', html: html), status: :unprocessable_entity
  end
end
Enter fullscreen mode Exit fullscreen mode

这看起来应该很眼熟。这个edit方法是另一个方法的镜像new,而另一个update方法又是另一个方法的镜像create。同样,submit:success当客户信息更新时,我们会触发事件,否则表单会重新渲染并显示错误。

最后,为了让页面上的每个模态链接都使用同一个模态控制器,我们将声明data-controller="modal"向上移动一级 DOM 树。customers/index.html.erb

<div class="max-w-3xl mx-auto mt-8" data-controller="modal">
  <div class="flex justify-between items-baseline mb-6">
    <!-- Snip -->
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

完成这些更改后,刷新客户索引页面,点击客户姓名,可以看到客户信息会在模态框中更新,并且在表单成功提交后,客户信息会在列表中直接更新。

优化模态开口

您在学习本指南的过程中可能已经注意到,模态框会在服务器内容渲染完成之前打开,因此模态框打开时会出现非常短暂的闪烁,然后迅速替换掉空白表单或表单的先前内容:

一段网页屏幕录像。用户多次打开和关闭“新客户”弹窗。每次打开时,弹窗都会短暂显示上次打开时的内容,然后内容才会更新。

这是因为点击模态框链接时模态框会立即打开,但从服务器检索表单片段的往返过程并非完全即时。

我们有多种方法可以避免这种情况,例如给模态框添加加载状态,以减少重新渲染带来的突兀感。但我将要演示的方法是,在从服务器获取内容之前,保持模态框隐藏。这给了我们另一个使用 CableReady 和 Stimulus 的机会,而这正是我们来这里的目的,对吧?

首先,向控制器添加另一个事件监听器modal

open() {
  document.addEventListener("modal:loaded", () => {
    this.containerTarget.classList.remove(this.toggleClass);
  }, { once: true });
  document.addEventListener("submit:success", () => {
    this.close()
  }, { once: true });

  document.body.classList.add('fixed', 'inset-x-0', 'overflow-hidden');
  document.body.insertAdjacentHTML('beforeend', this.backgroundHtml);
  this.background = document.querySelector(`#${this.backgroundId}`);
}
Enter fullscreen mode Exit fullscreen mode

我们在此进行了更新open,将调用containerTarget.classList.remove从立即执行改为响应modal:loadedDOM 事件执行。

这一变化意味着所有模态链接现在都已失效,因为modal:loaded事件永远不会发生,因此containerTarget.classList.remove永远不会运行,模态容器也始终保持隐藏状态。

CustomersController我们可以通过如下更新来修复模态框链接:

def new
  html = render_to_string(partial: 'form', locals: { customer: Customer.new })
  render operations: cable_car
    .outer_html('#customer_form', html: html)
    .dispatch_event(name: 'modal:loaded')
end

def edit
  html = render_to_string(partial: 'form', locals: { customer: @customer })
  render operations: cable_car
    .outer_html('#customer_form', html: html)
    .dispatch_event(name: 'modal:loaded')
end
Enter fullscreen mode Exit fullscreen mode

new在这两种edit方法中,我们再次利用 CableReady 的链式操作在替换modal:loaded后进行分发。outer_html

更改后,用户点击模态链接时的事件顺序如下:

  1. 向服务器发出请求
  2. 打开操作已触发
  3. 页面已应用模态背景,但模态框尚未可见。
  4. 表单内容已替换
  5. 模态框加载事件已触发。
  6. 模态框的隐藏类被移除,使其可见。

在我们的测试环境中,这一系列操作发生得非常快,用户几乎感觉不到背景应用和模态框显示之间的延迟。在生产环境中,您可能会发现,对于立即打开的模态框,加载状态可能是一种更具可扩展性的选择,但我们在这里的目的是学习 CableReady 和 Mrujs,而不是构建生产应用程序。

经过这些更改后,模态框打开时将预先填充更新后的内容,从而消除旧内容的闪烁。

一段屏幕录像显示一个初始为空白的网页,网页顶部标题为“客户”,并包含一个创建新客户的链接。用户点击该链接后,屏幕上会弹出一个模态窗口。用户输入姓名创建客户,页面会自动更新显示新客户的信息。用户继续添加和更新多个客户记录,每次表单都会以模态窗口的形式打开,页面也会立即更新显示用户的更改。

单个modal连接的 div 可以用于显示任意数量的模态框,从而减少传统应用程序中的初始页面加载时间,因为传统应用程序可能会预先渲染每个编辑模态框。

总结

今天我们学习了如何构建由 Stimulus、CableReady 和 Mrujs 提供支持的服务器端渲染模态表单。

Stimulus 和 CableReady 是两款功能强大、久经考验的工具,拥有成熟的功能集,任何现代 Rails 应用都应该考虑使用它们。CableReady 可以独立运行,通过多种方式向最终用户提供实时更新;也可以与StimulusReflex结合使用,提供类似 SPA 的体验,但无需 SPA 本身。

Mrujs 是一个较新的工具,目前仍在积极开发中,旨在作为现代、稳定的替代品rails/ujs,取代不再积极开发且将在 Rails 7 发布时弃用的工具。

除了我们今天看到的与 CableReady 的 Cable Car 的紧密集成之外,Mrujs 还以现代化的软件包形式提供了简单的确认对话框、禁用链接以及 Rails UJS 的其他便利功能。

在结束之前,需要特别说明一点:我们可以使用 Rails 生态系统中的各种工具来构建非常类似的用户体验,包括 Turbo Streams(这里有一份相关指南)。

虽然完整的Hotwire 堆栈也能以大致相同的努力实现这种体验,但恕我直言,CableReady 的链式操作的强大功能和灵活性使得 CableReady + Mrujs 比完整的 Hotwire 堆栈更适合这种特定的使用场景。

真正令人兴奋的是,作为 Rails 开发者,我们拥有大量强大的工具来构建实时响应式应用程序。这意味着无论我们最常使用哪种工具,我们都能从中受益。

继续使用 CableReady、Stimulus 和 Mrujs,获取以下资源:

今天就到这里。

一如既往,感谢阅读!

文章来源:https://dev.to/davidcolbyatx/server-rendered-modal-forms-on-rails-with-cableready-mrujs-stimulus-and-tailwind-2mne