如何在Jekyll中创建带自定义上下文的Block Tag查询数据对象
如何在Jekyll中创建根据ID查找对象的自定义Block Tag
首先先确认你的_data/array.yml格式要正确,每个对象的键值对需换行缩进,不然Jekyll没法正确解析:
- id: id1 name: name1 - id: id2 name: name2
接下来我们把你写的ItemBlock类补全,实现根据指定ID查找对象并传入上下文的功能:
module Jekyll class ItemBlock < Liquid::Block def initialize(tag_name, markup, tokens) super # 提取标记中的ID,去掉前后多余空格 @item_id = markup.strip end def render(context) # 获取Jekyll的site核心对象 site = context.registers[:site] # 从_data/array.yml中匹配对应ID的项 item = site.data['array'].find { |item| item['id'] == @item_id } # 先保存上下文中原有的item变量(避免覆盖原有数据) original_item = context['item'] # 将找到的目标项传入模板上下文 context['item'] = item if item # 渲染块内的模板内容,此时上下文已包含目标item content = super(context) # 恢复原来的item变量,防止污染后续模板渲染 context['item'] = original_item content end end end # 注册自定义Block Tag,让Liquid能识别{% item %}标签 Liquid::Template.register_tag('item', Jekyll::ItemBlock)
代码细节解释:
initialize方法:
- 调用
super继承Liquid::Block的基础初始化逻辑 - 把传入的标记内容(比如示例里的
id1)清理掉前后空格,保存为@item_id,后续用来匹配数组项
- 调用
render方法:
- 通过
context.registers[:site]拿到Jekyll的site实例,以此访问site.data下的数组数据 - 用
find方法遍历数组,精准匹配id一致的对象 - 先缓存上下文中原有的
item变量(如果存在的话),避免自定义逻辑覆盖原有模板变量 - 将找到的对象赋值给上下文的
item,这样块标签内部就能用{{ item.name }}直接访问属性 - 调用
super(context)渲染块内的模板内容,此时上下文已经携带了目标item - 最后恢复原来的
item变量,保证后续模板渲染不受影响
- 通过
示例用法:
你可以像这样在模板中使用这个自定义标签:
{% item id1 %} <p>数组总长度:{{ site.data.array.length }}</p> <p>当前项名称:{{ item.name }}</p> {% enditem %}
渲染后的HTML会是:
<p>数组总长度:2</p> <p>当前项名称:name1</p>
如果指定的ID不存在,item会是nil,此时{{ item.name }}不会输出任何内容。你也可以在render方法里加个判断逻辑,比如没找到时输出提示信息,或者直接返回空内容,完全可以根据自己的需求调整。
内容的提问来源于stack exchange,提问作者kbariotis
相关产品推荐
相关产品推荐

