页面不应把“找六篇最新文章”的结果写死在 layout 里。先声明一个内容 source,再在 layout 的顶层 props 中引用它。source 是四个字段的一个小合同:path、可选的 sort、可选的 limit 与可选的 filter。
在页面作用域声明 source
一个页面可以在 pages/<page>/sources/ 下声明 source。下列文件共同定义名为 related 的 source:
pages/topic/sources/
├── related # /content/articles/
├── related.sort # -date
├── related.limit # 6
└── related.filter # tags=AFS,Web Device
# category=Researchrelated 文件内容是 source path,例如 /content/articles/。.sort 与 .limit 是可选的。.filter 一行一个条件:行与行之间是 AND;同一行逗号分隔的值是 OR。上例的含义是“tag 包含 AFS 或 Web Device,并且 category 精确等于 Research”。字段匹配目前是精确匹配、区分大小写;缺少该字段的对象不匹配。
source path 必须位于 /content/<type>/ 下。它也可指向集合内子路径,以缩小范围;不要写 .. 或把任意文件系统路径当作内容 source。无效的 source path 会得到空结果,而不是越过内容根目录读取其他文件。
在 layout 中绑定
source 名称在其页面或集合 scope 内解析。layout 用完整的占位值引用它,例如:
items=$source.related或按需要读取其可用路径。不要把 $source.related 混在一段普通 prose 中,也不要在嵌套的任意对象里猜它会被解析:当前 source-binding 检查只把 section 自己顶层 props 的完整 $source.<name> 视为声明性绑定。
同名 source 可以在不同页面表示不同查询;它不是全站全局变量。页面 topic 的 $source.related 应由 pages/topic/sources/related(或该集合记录的 source 声明)回答,而不能依赖另一个页面的同名文件。
让空结果可诊断
未声明的 $source.<name> 曾经容易让页面静默显示空列表。当前 runtime 能检查 layout 需要的 source 是否在同一 scope 声明,并把问题标成 source-binding-undeclared,同时列出该 scope 已声明的名称。仍应在浏览器中检查数据是否符合预期:一个存在的 source 也可以因为路径、filter、locale 或内容本身而返回空集合。
推荐的验收顺序:
- 先用一个没有 filter 的
/content/<type>/source 验证列表与详情对象能出现。 - 再加入
sort、limit,最后才加入 filter。 - 每加入一层,运行 DSL/站点检查和构建,并看页面真实结果。
- 把“0 条结果是合理的”写进组件空状态,而不是把缺少数据藏起来。
内容对象如何声明 tags 与关系,见内容对象、元数据与语言;完整字段边界见来源绑定参考。