MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Ruby on Rails 视图与模板引擎

2023-12-176.5k 阅读

Ruby on Rails 视图基础

在 Ruby on Rails 应用程序中,视图(View)扮演着向用户呈现数据的关键角色。视图负责将从控制器(Controller)传来的数据以合适的格式展示给用户,通常是以 HTML 的形式,但也可以是 JSON、XML 等其他格式。

Rails 中的视图主要基于模板引擎来构建。模板引擎允许我们在普通文本文件(如 HTML 文件)中嵌入 Ruby 代码,从而动态生成内容。这使得我们可以轻松地将数据与展示逻辑分离,提高代码的可维护性和可扩展性。

视图文件的位置与命名约定

在 Rails 项目中,视图文件通常位于 app/views 目录下。每个控制器都有一个对应的子目录,其中存放着与该控制器相关的视图文件。例如,对于 PostsController,其视图文件会放在 app/views/posts 目录中。

视图文件的命名通常与控制器的动作(action)相对应。比如,PostsControllerindex 动作对应的视图文件名为 index.html.erb。这里的 .html 表示生成的是 HTML 格式的内容,而 .erb 则表示使用的是 ERB 模板引擎(这是 Rails 默认使用的模板引擎)。

简单视图示例

假设我们有一个简单的 Rails 应用,用于展示文章列表。首先,在 PostsController 中定义 index 动作:

class PostsController < ApplicationController
  def index
    @posts = Post.all
  end
end

这里,@posts 实例变量将从数据库中获取所有的文章记录,并传递给视图。

然后,在 app/views/posts/index.html.erb 中编写视图代码:

<h1>文章列表</h1>
<ul>
  <% @posts.each do |post| %>
    <li><%= post.title %></li>
  <% end %>
</ul>

在这段代码中,我们使用了 ERB 模板引擎的语法。<% %> 用于执行 Ruby 代码块,而 <%= %> 用于输出 Ruby 代码的结果。这里,我们通过 @posts.each 循环遍历每一篇文章,并输出文章的标题。

ERB 模板引擎深入解析

ERB(Embedded Ruby)是 Ruby 标准库中自带的模板引擎,也是 Rails 默认使用的模板引擎。它允许我们在文本文件(如 HTML、XML 等)中嵌入 Ruby 代码,从而生成动态内容。

ERB 语法基础

  1. 代码执行块<% code %> 用于执行 Ruby 代码块,但不输出结果。例如:
<% if user_signed_in? %>
  <p>欢迎,<%= current_user.name %>!</p>
<% end %>

在这个例子中,if user_signed_in? 是一个 Ruby 条件判断语句,用于检查用户是否已登录。如果用户已登录,则会执行 <p>欢迎,<%= current_user.name %>!</p> 这段代码,输出欢迎信息。

  1. 代码输出块<%= expression %> 用于输出 Ruby 表达式的结果。例如,<%= post.title %> 会输出 post 对象的 title 属性值。

  2. 注释<%# comment %> 用于在 ERB 模板中添加注释。这些注释不会在生成的输出中显示。例如:

<%# 这是一个注释,用于说明下面代码的作用 %>
<%= link_to '文章详情', post_path(post) %>

ERB 中的局部变量与实例变量

在 ERB 模板中,可以使用局部变量和实例变量。局部变量的作用域仅限于当前模板文件,而实例变量则是从控制器传递过来的,可以在整个视图中使用。

例如,在控制器中定义一个实例变量 @message

class WelcomeController < ApplicationController
  def index
    @message = '欢迎来到我们的网站!'
  end
end

在视图 app/views/welcome/index.html.erb 中就可以使用这个实例变量:

<p><%= @message %></p>

而局部变量可以在模板中直接定义和使用,例如:

<% count = 0 %>
<% @items.each do |item| %>
  <li><%= count += 1 %> - <%= item.name %></li>
<% end %>

这里的 count 就是一个局部变量,用于给列表项编号。

ERB 模板的布局与部分视图

  1. 布局(Layout):布局是一种用于定义应用程序整体结构的模板。在 Rails 中,默认的布局文件位于 app/views/layouts/application.html.erb。布局文件通常包含 HTML 的基本结构,如 <html><head><body> 标签等,并且会预留一个位置(通常使用 <%= yield %>)来插入具体视图的内容。

例如,application.html.erb 可能如下:

<!DOCTYPE html>
<html>
<head>
  <title>My Rails App</title>
  <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
  <%= yield %>
</body>
</html>

这里的 <%= yield %> 就像一个占位符,当访问具体的视图(如 posts/index.html.erb)时,该视图的内容会被插入到这个位置。

  1. 部分视图(Partial):部分视图是一种可以在多个视图中复用的小模板。部分视图文件通常以 _ 开头命名,例如 _post.html.erb。可以使用 render 方法在其他视图中渲染部分视图。

假设我们有一个 _post.html.erb 部分视图,用于展示一篇文章的基本信息:

<div class="post">
  <h2><%= post.title %></h2>
  <p><%= post.excerpt %></p>
</div>

posts/index.html.erb 中,可以这样渲染这个部分视图:

<h1>文章列表</h1>
<% @posts.each do |post| %>
  <%= render partial: 'post', locals: { post: post } %>
<% end %>

这里通过 locals 选项将当前的 post 对象传递给部分视图,使得部分视图可以使用这个对象来展示文章信息。

其他模板引擎

虽然 ERB 是 Rails 默认的模板引擎,但 Rails 也支持使用其他模板引擎,如 Haml、Slim 等。这些模板引擎提供了不同的语法风格,以满足不同开发者的偏好和项目需求。

Haml 模板引擎

Haml 是一种简洁的模板语言,它使用缩进和特殊字符来代替传统的 HTML 标签。例如,下面是一个使用 Haml 语法的简单视图示例:

%h1 文章列表
%ul
  - @posts.each do |post|
    %li= post.title

在这个例子中,% 符号用于表示 HTML 标签,如 %h1 表示 <h1> 标签。- 符号用于执行 Ruby 代码块,而 = 符号用于输出 Ruby 表达式的结果。

要在 Rails 项目中使用 Haml,首先需要在 Gemfile 中添加 gem 'haml',然后运行 bundle install 安装该 gem。安装完成后,可以将视图文件的扩展名从 .html.erb 改为 .html.haml,Rails 就会自动使用 Haml 来渲染这些视图。

Slim 模板引擎

Slim 也是一种简洁的模板引擎,它的语法与 Haml 有些相似,但更加简洁。例如,同样的文章列表视图用 Slim 语法可以这样写:

h1 文章列表
ul
  - @posts.each do |post|
    li= post.title

Slim 省略了 Haml 中的 % 符号,直接使用标签名。要在 Rails 项目中使用 Slim,在 Gemfile 中添加 gem 'slim',然后运行 bundle install。之后,将视图文件扩展名改为 .html.slim 即可。

视图与数据交互

视图在 Rails 应用程序中不仅负责展示数据,还需要与用户进行交互,收集用户输入的数据并将其传递回控制器进行处理。

表单(Form)

表单是用户与应用程序进行交互的重要方式。在 Rails 中,可以使用 form_withform_for 方法来生成表单。

  1. form_with 方法form_with 是 Rails 5.1 引入的一个更通用的表单生成方法,它可以处理不同类型的资源(如新建资源、编辑资源等)。

例如,要创建一个用于新建文章的表单:

<%= form_with(model: @post, local: true) do |form| %>
  <div>
    <%= form.label :title %>
    <%= form.text_field :title %>
  </div>
  <div>
    <%= form.label :content %>
    <%= form.text_area :content %>
  </div>
  <%= form.submit '创建文章' %>
<% end %>

在这个例子中,model: @post 表示这个表单是用于处理 @post 对象的。local: true 表示表单提交时不会使用 AJAX(如果不设置这个选项,Rails 默认会使用 AJAX 提交表单)。form.labelform.text_field 等方法用于生成表单标签和输入字段。

  1. form_for 方法form_for 是一个更专门用于处理 ActiveRecord 对象的表单生成方法。它的使用方式与 form_with 类似,但语法上稍有不同。

例如:

<%= form_for(@post) do |form| %>
  <div>
    <%= form.label :title %>
    <%= form.text_field :title %>
  </div>
  <div>
    <%= form.label :content %>
    <%= form.text_area :content %>
  </div>
  <%= form.submit '创建文章' %>
<% end %>

form_for 会根据 @post 对象的状态(新建或已存在)自动生成合适的表单 URL 和 HTTP 方法(如新建时使用 POST 方法,编辑时使用 PUTPATCH 方法)。

处理表单数据

当用户提交表单后,表单数据会被发送到控制器的指定动作中。在控制器中,可以通过 params 对象来获取表单数据。

例如,对于上面新建文章的表单,在 PostsController 中可以这样处理表单数据:

class PostsController < ApplicationController
  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to @post, notice: '文章创建成功!'
    else
      render :new
    end
  end

  private
  def post_params
    params.require(:post).permit(:title, :content)
  end
end

create 动作中,首先通过 post_params 方法获取并过滤表单数据(params.require(:post) 表示表单数据必须包含 post 键,permit(:title, :content) 表示只允许 titlecontent 这两个参数)。然后使用这些数据创建一个新的 Post 对象,并尝试保存到数据库中。如果保存成功,重定向到文章详情页面;如果失败,则重新渲染新建文章的表单,以便用户修改错误。

视图中的辅助方法(Helpers)

Rails 提供了丰富的辅助方法(Helpers)来简化视图中的常见操作,如生成链接、格式化日期时间、处理文本等。

链接辅助方法

  1. link_to 方法link_to 方法用于生成 HTML 链接。它的基本语法是 link_to '链接文本', 目标路径

例如,要生成一个指向文章详情页面的链接:

<%= link_to post.title, post_path(post) %>

这里 post.title 是链接显示的文本,post_path(post) 是链接的目标路径。post_path 是 Rails 根据资源路由自动生成的路径辅助方法,它会根据 post 对象的 id 生成正确的路径。

  1. button_to 方法button_to 方法用于生成看起来像按钮的链接,并且可以指定 HTTP 方法(如 POSTDELETE 等)。

例如,要生成一个删除文章的按钮:

<%= button_to '删除文章', post_path(post), method: :delete, data: { confirm: '确定要删除这篇文章吗?' } %>

这里 method: :delete 表示使用 DELETE 方法提交请求,data: { confirm: '确定要删除这篇文章吗?' } 会在点击按钮时弹出一个确认对话框。

日期与时间辅助方法

  1. date_format 方法:用于格式化日期。例如,要将日期格式化为 YYYY - MM - DD 的形式:
<%= l @post.created_at, format: :long %>

这里 @post.created_at 是一个 DateTime 对象,format: :long 表示使用预定义的长格式(如 2023 年 10 月 15 日)。也可以自定义格式,如 format: '%Y-%m-%d' 会输出 2023-10-15

  1. time_ago_in_words 方法:用于显示从某个时间点到现在的时间间隔,以人类可读的形式。例如:
<p>这篇文章发布于 <%= time_ago_in_words @post.created_at %> 前</p>

如果 @post.created_at 是 30 分钟前,会输出 这篇文章发布于 30 分钟前

文本处理辅助方法

  1. truncate 方法:用于截断文本,并在截断处添加省略号。例如,要截断文章摘要为 50 个字符:
<%= truncate @post.excerpt, length: 50 %>
  1. simple_format 方法:用于将文本中的换行符转换为 <br> 标签,并将段落转换为 <p> 标签。例如:
<%= simple_format @post.content %>

这样可以将文章内容中的换行和段落格式正确显示在 HTML 页面中。

视图的性能优化

在开发 Rails 应用程序时,视图的性能优化是非常重要的,它直接影响用户体验。以下是一些常见的视图性能优化方法。

减少视图中的逻辑

视图应该尽量保持简单,只负责展示数据,避免在视图中编写复杂的业务逻辑。如果需要进行复杂的计算或数据处理,应该在控制器或模型中完成,然后将处理好的数据传递给视图。

例如,不要在视图中进行复杂的数据库查询或循环嵌套计算,而是在控制器中提前准备好所需的数据。

缓存视图片段

Rails 提供了缓存机制,可以对视图中的部分内容进行缓存,以减少重复渲染的开销。可以使用 cache 方法来缓存视图片段。

例如,对于一些不经常变化的页面部分,如网站的导航栏:

<% cache('navigation') do %>
  <ul>
    <li><%= link_to '首页', root_path %></li>
    <li><%= link_to '文章', posts_path %></li>
  </ul>
<% end %>

这里 cache('navigation') 表示将这段代码的渲染结果缓存起来,缓存键为 navigation。下次渲染视图时,如果缓存存在,就直接使用缓存内容,而不会重新渲染这部分代码。

优化图片和资源加载

  1. 图片优化:在视图中使用图片时,确保图片的尺寸合适,避免加载过大的图片。可以使用图像处理工具(如 ImageMagick 或 MiniMagick)在服务器端对图片进行裁剪和压缩。

例如,在 Rails 中可以使用 image_tag 方法来显示图片,并指定图片的尺寸:

<%= image_tag 'logo.png', width: 200, height: 100 %>
  1. 资源合并与压缩:将多个 CSS 和 JavaScript 文件合并成一个文件,并进行压缩,以减少浏览器的请求次数和文件大小。Rails 提供了 Asset Pipeline 来帮助管理和优化资源文件。可以在 config/environments/production.rb 中配置资源合并和压缩选项:
config.assets.js_compressor = :uglifier
config.assets.css_compressor = :sass
config.assets.compile = true
config.assets.digest = true

这样在生产环境中,Rails 会自动合并和压缩 CSS 和 JavaScript 文件,提高页面加载速度。

通过以上对 Ruby on Rails 视图与模板引擎的深入了解和优化方法,开发者可以构建出高效、美观且易于维护的 Web 应用程序界面,为用户提供更好的体验。在实际开发中,应根据项目的具体需求和特点,灵活选择和应用这些技术。