Rails Turbo/Hotwire 指南
无需大量 JavaScript 构建类 SPA 的 Rails 应用:Turbo Drive、Turbo Frames、Turbo Streams 和 Stimulus。
1. Turbo Drive
<!-- Turbo Drive 拦截所有链接点击和表单提交,仅替换 <body> -->
<!-- 禁用特定链接 -->
<a href="/download" data-turbo="false">下载 PDF</a>
# 控制器 — 创建后重定向
class ArticlesController < ApplicationController
def create
@article = Article.new(article_params)
if @article.save
redirect_to @article, notice: "文章已创建!"
else
render :new, status: :unprocessable_entity
end
end
end
2. Turbo Frames
<!-- 用 turbo-frame 包裹区域 -->
<turbo-frame id="article_form">
<%= render "form", article: @article %>
</turbo-frame>
<!-- 懒加载框架 -->
<turbo-frame id="sidebar_stats" src="/stats/sidebar" loading="lazy">
<p>加载中...</p>
</turbo-frame>
3. Turbo Streams
class CommentsController < ApplicationController
def create
@comment = @article.comments.build(comment_params.merge(user: current_user))
if @comment.save
respond_to do |format|
format.turbo_stream do
render turbo_stream: [
turbo_stream.prepend("comments", partial: "comment", locals: { comment: @comment }),
turbo_stream.update("comment_form", partial: "form", locals: { comment: Comment.new }),
]
end
format.html { redirect_to @article }
end
end
end
end
4. Stimulus 控制器
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["input", "count"]
static values = { max: { type: Number, default: 280 } }
update() {
const remaining = this.maxValue - this.inputTarget.value.length
this.countTarget.textContent = remaining
}
}
<!-- HTML -->
<div data-controller="character-count">
<textarea data-character-count-target="input"
data-action="input->character-count#update"></textarea>
<span data-character-count-target="count"></span> 剩余
</div>