<body>
và hợp nhất phần <head>
, giúp trải nghiệm duyệt web nhanh hơn.<%# app/views/products/index.html.erb %><h1>Sản phẩm</h1><%= turbo_frame_tag "product_list" do %> <div class="products"> <%= render @products %> </div><% end %><%= turbo_frame_tag "product_detail" %>
<%# app/views/products/_product.html.erb %><div class="product"> <%= link_to product.name, product, data: { turbo_frame: "product_detail" } %></div>
<%# app/views/products/show.html.erb %><%= turbo_frame_tag "product_detail" do %> <div class="product-detail"> <h2><%= @product.name %></h2> <p><%= @product.description %></p> <p>Giá: <%= @product.price %></p> </div><% end %>
# app/controllers/comments_controller.rbdef create @comment = @post.comments.create!(comment_params) respond_to do |format| format.html { redirect_to @post } format.turbo_stream endend
<%# app/views/comments/create.turbo_stream.erb %><turbo-stream action="append" target="comments"> <%= render partial: "comments/comment", locals: { comment: @comment } %></turbo-stream><turbo-stream action="update" target="new_comment"> <%= render partial: "comments/form", locals: { post: @post, comment: Comment.new } %></turbo-stream>
# app/models/comment.rbclass Comment < ApplicationRecord belongs_to :post after_create_commit -> { broadcast_append_to post }end
<%= turbo_stream_from @post %><div id="comments"> <%= render @post.comments %></div>
<%# app/views/dashboard/show.html.erb %><%= turbo_frame_tag "dashboard", morph: true do %> <div class="dashboard"> <div class="metrics"> <%= render "metrics", data: @metrics %> </div> <div class="recent-activity"> <%= render "activities", activities: @activities %> </div> </div><% end %>
<%= link_to "Cập nhật", dashboard_path, data: { turbo_frame: "dashboard" } %>
# app/controllers/dashboard_controller.rbdef show @metrics = current_user.metrics @activities = current_user.recent_activities(25)end
Công cụ | Khi nào sử dụng |
---|---|
Turbo Drive | Nâng cao tốc độ điều hướng cho ứng dụng đa trang truyền thống |
Turbo Frames | Cập nhật một phần giao diện, xây dựng component độc lập, master-detail |
Turbo Streams | Tính năng thời gian thực, cập nhật đa phần tử, tương tác đa người dùng |
Turbo Morph | UI phức tạp, cần tối ưu cập nhật chi tiết, giữ trạng thái DOM |
<%# app/views/posts/show.html.erb %><article class="post"> <h1><%= @post.title %></h1> <div class="content"><%= @post.content %></div>
<h2>Bình luận (<span id="comment-count"><%= @post.comments.count %></span>)</h2> <%= turbo_stream_from @post, :comments %>
<div id="comments" class="comments"> <%= render @post.comments %> </div>
<%= turbo_frame_tag "new_comment" do %> <%= render "comments/form", post: @post, comment: Comment.new %> <% end %></article>
<%# app/views/comments/_form.html.erb %><%= form_with model: [post, comment], data: { controller: "reset-form" } do |form| %> <%= form.text_area :content, placeholder: "Thêm bình luận..." %> <%= form.submit "Gửi" %><% end %>
# app/controllers/comments_controller.rbclass CommentsController < ApplicationController before_action :set_post
def create @comment = @post.comments.build(comment_params) @comment.user = current_user respond_to do |format| if @comment.save format.turbo_stream else format.turbo_stream { render turbo_stream: turbo_stream.replace("new_comment", partial: "comments/form", locals: { post: @post, comment: @comment }) } end end end
private
def set_post @post = Post.find(params[:post_id]) end
def comment_params params.require(:comment).permit(:content) endend
<%# app/views/comments/create.turbo_stream.erb %><turbo-stream action="append" target="comments"> <%= render "comments/comment", comment: @comment %></turbo-stream><turbo-stream action="update" target="comment-count"> <%= @post.comments.count %></turbo-stream><turbo-stream action="replace" target="new_comment"> <%= render "comments/form", post: @post, comment: Comment.new %></turbo-stream>
# app/models/comment.rbclass Comment < ApplicationRecord belongs_to :post belongs_to :user broadcasts_to ->(comment) { [comment.post, :comments] }, inserts_by: :appendend