跳过正文

第11篇:ActionView 渲染

·669 字·4 分钟
xieweicong
作者
xieweicong

学习目标:理解视图渲染机制和 Helper 系统

1. 视图基础
#

1.1 模板类型
#

# ERB (Embedded Ruby)
app/views/posts/index.html.erb

# Builder (XML)
app/views/posts/index.xml.builder

# Jbuilder (JSON)
app/views/posts/index.json.jbuilder

1.2 ERB 语法
#

<% # Ruby 代码,不输出 %>
<% @posts.each do |post| %>
  <%= # Ruby 代码,输出结果 %>
  <%= post.title %>

  <%# 注释 %>
  <%# 这是注释 %>

  <%== # 不转义 HTML %>
  <%== post.html_content %>
<% end %>

2. 布局和模板
#

2.1 布局
#

<!-- app/views/layouts/application.html.erb -->
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) || "My App" %></title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= stylesheet_link_tag "application" %>
    <%= javascript_include_tag "application" %>
  </head>
  <body>
    <%= render 'shared/header' %>
    <%= yield %>  <!-- 主内容 -->
    <%= render 'shared/footer' %>
  </body>
</html>

2.2 指定布局
#

class AdminController < ApplicationController
  layout "admin"
end

# 或在 action 中
def show
  render layout: "special"
end

2.3 Content For
#

<!-- 在视图中 -->
<% content_for :title do %>
  My Page Title
<% end %>

<% content_for :scripts do %>
  <%= javascript_tag do %>
    console.log("Page loaded");
  <% end %>
<% end %>

<!-- 在布局中 -->
<title><%= yield(:title) %></title>
<%= yield(:scripts) %>

3. Partials (部分模板)
#

3.1 基本用法
#

<!-- 渲染部分模板 -->
<%= render 'form' %>
<%= render 'shared/menu' %>

<!-- 传递变量 -->
<%= render 'form', post: @post %>

<!-- 在部分模板中使用 -->
<!-- app/views/posts/_form.html.erb -->
<%= form_with(model: post) do |f| %>
  <%= f.text_field :title %>
<% end %>

3.2 集合渲染
#

<!-- 渲染集合 -->
<%= render @posts %>
<!-- 等价于 -->
<%= render partial: 'posts/post', collection: @posts %>

<!-- app/views/posts/_post.html.erb -->
<div class="post">
  <%= post.title %>
</div>

<!-- 自定义变量名 -->
<%= render partial: 'product', collection: @products, as: :item %>

3.3 间隔符
#

<%= render partial: 'post',
           collection: @posts,
           spacer_template: 'post_spacer' %>

4. Helpers
#

4.1 内置 Helpers
#

<!-- URL Helpers -->
<%= link_to "Posts", posts_path %>
<%= link_to "Edit", edit_post_path(@post) %>
<%= button_to "Delete", @post, method: :delete %>

<!-- 资源 Helpers -->
<%= image_tag "logo.png" %>
<%= javascript_include_tag "application" %>
<%= stylesheet_link_tag "application" %>

<!-- 表单 Helpers -->
<%= form_with model: @post do |f| %>
  <%= f.text_field :title %>
  <%= f.text_area :content %>
  <%= f.submit %>
<% end %>

<!-- 文本 Helpers -->
<%= truncate(@post.content, length: 100) %>
<%= pluralize(@posts.count, "post") %>
<%= time_ago_in_words(@post.created_at) %>
<%= number_to_currency(@product.price) %>

4.2 自定义 Helpers
#

# app/helpers/application_helper.rb
module ApplicationHelper
  def formatted_date(date)
    date.strftime("%B %d, %Y")
  end

  def active_link_to(name, path)
    class_name = current_page?(path) ? 'active' : ''
    link_to name, path, class: class_name
  end
end

<!-- 在视图中使用 -->
<%= formatted_date(@post.created_at) %>
<%= active_link_to "Home", root_path %>

5. 表单构建器
#

5.1 form_with
#

<%= form_with model: @post do |f| %>
  <%= f.label :title %>
  <%= f.text_field :title %>

  <%= f.label :content %>
  <%= f.text_area :content %>

  <%= f.label :published %>
  <%= f.check_box :published %>

  <%= f.submit %>
<% end %>

5.2 嵌套表单
#

<%= form_with model: @user do |f| %>
  <%= f.text_field :name %>

  <%= f.fields_for :profile do |profile_form| %>
    <%= profile_form.text_field :bio %>
  <% end %>

  <%= f.submit %>
<% end %>

6. 资源管道
#

6.1 Asset Pipeline
#

<!-- 图片 -->
<%= image_tag "logo.png" %>
<!-- 生成 -->
<img src="/assets/logo-[fingerprint].png">

<!-- CSS -->
<%= stylesheet_link_tag "application" %>

<!-- JavaScript -->
<%= javascript_include_tag "application" %>

6.2 Importmap (Rails 7+)
#

# config/importmap.rb
pin "application", preload: true
pin "@hotwired/turbo-rails", to: "turbo.min.js"

<!-- 在视图中 -->
<%= javascript_importmap_tags %>

7. 缓存
#

7.1 Fragment Caching
#

<% cache @post do %>
  <div class="post">
    <%= @post.title %>
    <%= @post.content %>
  </div>
<% end %>

<!-- 缓存集合 -->
<% @posts.each do |post| %>
  <% cache post do %>
    <%= render post %>
  <% end %>
<% end %>

7.2 Russian Doll Caching
#

<!-- 外层缓存 -->
<% cache @post do %>
  <%= @post.title %>

  <!-- 内层缓存 -->
  <% cache [@post, 'comments'] do %>
    <%= render @post.comments %>
  <% end %>
<% end %>

8. 视图渲染原理
#

8.1 模板查找
#

# Rails 按顺序查找模板:
1. app/views/posts/show.html.erb
2. app/views/posts/show.html.builder
3. app/views/application/show.html.erb

8.2 渲染器
#

# actionview/lib/action_view/renderer.rb
class Renderer
  def render(context, options)
    template = find_template(options[:template])
    template.render(context, options[:locals])
  end
end

9. 本章总结
#

ActionView 提供:

  • 多种模板类型(ERB, Builder, Jbuilder)
  • 布局和部分模板系统
  • 丰富的 Helper 方法
  • 表单构建器
  • Fragment Caching

上一篇Controller 详解 下一篇ActiveJob 任务队列 返回学习指南首页