不使用Rails/JS,仅通过Ruby/ERB捕获复用HTML代码块的方法
原生Ruby/ERB实现HTML代码块重复调用的方案
完全可以仅用原生Ruby/ERB实现类似Rails的content_for功能,不需要依赖Rails框架,实现方式和你在Rails中的使用习惯几乎一致。
实现原理
只需要在ERB的渲染上下文中维护一个存储命名内容块的哈希,封装两类逻辑即可:
- 调用时传入代码块:捕获块内的ERB渲染结果,存入对应命名的哈希槽位
- 调用时不传代码块:直接返回对应命名槽位已存储的内容
完整实现示例
第一步:编写核心逻辑代码
require 'erb' # 定义ERB渲染上下文类,存储内容块和实现content_for方法 class ERBContext def initialize @content_blocks = {} end def content_for(name, &block) if block_given? # 捕获块内的渲染结果存入哈希 @content_blocks[name.to_s] = block.call else # 直接返回已存储的内容 @content_blocks[name.to_s] end end # 暴露binding供ERB渲染调用 def get_binding binding end end
第二步:编写ERB模板
你可以把下面内容存为template.erb,用法和你在Rails中的写法完全一致:
<% content_for :mycontent do %> <div class="reusable-block"> some html code that I want to capture etc </div> <% end %> <!-- 第一次复用代码块 --> <%= content_for :mycontent %> <!-- 第二次复用代码块 --> <p>下面是第二次调用的内容:</p> <%= content_for :mycontent %>
第三步:渲染ERB模板
# 初始化上下文 context = ERBContext.new # 读取模板文件 template = File.read('template.erb') # 渲染ERB renderer = ERB.new(template) result = renderer.result(context.get_binding) # 输出最终渲染结果 puts result
进阶优化(可选)
如果需要支持追加内容而不是覆盖原有内容,可以修改content_for方法:
def content_for(name, append: false, &block) name = name.to_s if block_given? content = block.call if append && @content_blocks[name] @content_blocks[name] += content else @content_blocks[name] = content end else @content_blocks[name] end end
调用时添加append: true参数即可实现内容追加:
<% content_for :mycontent, append: true do %> <p>追加的额外内容</p> <% end %>
内容的提问来源于stack exchange,提问作者collimarco
相关产品推荐
相关产品推荐

