User 69e88e27
发布于:2026-01-13
# layout 标签使用指南
## 概述
`layout` 标签用于设置模板使用的布局文件,或者禁用布局渲染。布局文件提供了页面的整体结构(如 HTML 骨架、导航栏、页脚等),模板内容会被插入到布局的指定位置。
## 语法
```liquid
{% layout "布局名称" %} <!-- 使用指定布局 -->
{% layout none %} <!-- 不使用布局 -->
```
## 布局文件位置
布局文件位于主题的 `layout/` 目录下,例如:
- `layout/theme.liquid` - 默认主题布局
- `layout/custom.liquid` - 自定义布局
- `layout/mobile.liquid` - 移动端布局
## 使用示例
### 1. 使用默认布局
如果不设置 `layout` 标签,模板会默认使用 `layout/theme.liquid` 布局。
```liquid
<h1>页面标题</h1>
<p>页面内容</p>
```
模板内容会被插入到布局文件的 `{{ content_for_layout }}` 位置。
### 2. 使用自定义布局
指定使用特定的布局文件。
```liquid
{% layout "custom" %}
<h1>页面标题</h1>
<p>页面内容</p>
```
这会使用 `layout/custom.liquid` 作为布局文件。
### 3. 禁用布局
当需要返回完整的 HTML 页面或非 HTML 格式的响应时,禁用布局。
```liquid
{% layout none %}
<html>
<head>
<title>独立页面</title>
</head>
<body>
<h1>完整 HTML 页面</h1>
</body>
</html>
```
### 4. 条件设置布局
根据条件动态选择不同的布局。
```liquid
{% if params.mobile == "true" %}
{% layout "mobile" %}
{% else %}
{% layout "desktop" %}
{% endif %}
<h1>页面标题</h1>
<p>页面内容</p>
```
### 5. 配合 response_type 使用
当使用非 HTML 响应类型时,必须禁用布局。
```liquid
{% response_type "json" %}
{% layout none %}
{
"status": "success",
"data": {}
}
```
```liquid
{% response_type "turbo_stream" %}
{% layout none %}
<turbo-stream action="replace" target="content">
<template>
<div id="content">更新后的内容</div>
</template>
</turbo-stream>
```
## 布局文件结构
布局文件通常包含页面的基本结构,模板内容会被插入到 `content_for_layout` 变量位置。
**示例:`layout/theme.liquid`**
```liquid
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{{ page.title }}</title>
{% meta_tags %}
</head>
<body>
<header>
<!-- 导航栏 -->
</header>
<main>
{{ content_for_layout }}
</main>
<footer>
<!-- 页脚 -->
</footer>
</body>
</html>
```
## 实际应用场景
### 场景 1:不同设备使用不同布局
```liquid
{% if params.device == "mobile" %}
{% layout "mobile" %}
{% elsif params.device == "tablet" %}
{% layout "tablet" %}
{% else %}
{% layout "desktop" %}
{% endif %}
<h1>响应式页面</h1>
```
### 场景 2:API 接口不使用布局
```liquid
{% response_type "json" %}
{% layout none %}
{
"articles": [
{% for article in articles %}
{
"id": {{ article.id }},
"title": {{ article.title | json }}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
}
```
### 场景 3:错误页面使用特殊布局
```liquid
{% layout "error" %}
{% response_status 404 %}
<div class="error-page">
<h1>404 - 页面未找到</h1>
<p>抱歉,您访问的页面不存在。</p>
</div>
```
### 场景 4:打印页面使用简化布局
```liquid
{% layout "print" %}
<h1>{{ page.title }}</h1>
<div class="content">
{{ page.body }}
</div>
```
## 注意事项
1. **布局包装**:使用布局时,模板内容会被包装在布局的 `content_for_layout` 变量位置,而不是直接输出
2. **禁用布局**:使用 `{% layout none %}` 时,模板内容会直接输出,不会被任何布局包装,此时模板需要包含完整的 HTML 结构(如果返回 HTML 格式)
3. **必须配合 response_type**:当使用非 HTML 响应类型(如 `turbo_stream`、`json`、`xml`)时,必须禁用布局,避免布局的 HTML 结构影响响应格式
4. **布局优先级**:如果模板和布局中都设置了 `response_type` 或 `response_status`,布局中的设置会覆盖模板中的设置
5. **标签顺序**:将 `layout` 标签放在模板的最前面,确保在渲染过程中正确设置布局
6. **布局文件存在性**:确保指定的布局文件存在于 `layout/` 目录中,否则会使用默认布局或报错
## 常见错误
### 错误 1:非 HTML 响应未禁用布局
```liquid
{%# ❌ 错误示例 %}
{% response_type "json" %}
<!-- 没有设置 layout none -->
{
"status": "success"
}
```
**问题**:响应会被布局的 HTML 结构包装,导致 JSON 解析失败。
**解决**:
```liquid
{%# ✅ 正确示例 %}
{% response_type "json" %}
{% layout none %}
{
"status": "success"
}
```
### 错误 2:禁用布局但内容不完整
```liquid
{%# ❌ 错误示例 %}
{% layout none %}
<h1>页面标题</h1>
<!-- 缺少完整的 HTML 结构 -->
```
**问题**:如果返回 HTML 格式,缺少完整的 HTML 结构可能导致页面显示异常。
**解决**:
```liquid
{%# ✅ 正确示例 - 返回完整 HTML %}
{% layout none %}
<!DOCTYPE html>
<html>
<head>
<title>页面标题</title>
</head>
<body>
<h1>页面标题</h1>
</body>
</html>
```
或者使用布局:
```liquid
{%# ✅ 正确示例 - 使用布局 %}
{% layout "theme" %}
<h1>页面标题</h1>
```
### 错误 3:布局文件不存在
```liquid
{%# ❌ 错误示例 %}
{% layout "nonexistent" %}
<h1>页面标题</h1>
```
**问题**:如果指定的布局文件不存在,可能会使用默认布局或报错。
**解决**:确保布局文件存在于 `layout/` 目录中,或使用存在的布局名称。
## 最佳实践
1. **非 HTML 响应禁用布局**:当使用 `response_type` 返回非 HTML 格式时,始终配合 `{% layout none %}` 禁用布局
2. **标签顺序**:将 `layout` 标签放在模板的最前面,与其他控制标签(如 `response_type`、`response_status`)一起
3. **条件布局**:根据设备、用户类型等条件动态选择布局,提供更好的用户体验
4. **布局复用**:创建通用的布局文件,减少重复代码
5. **测试验证**:确保在不同布局下页面显示正常,特别是响应式布局
## 总结
`layout` 标签用于控制模板的布局渲染,可以指定使用特定的布局文件,或者禁用布局。当需要返回非 HTML 格式的响应时,必须禁用布局以避免 HTML 结构污染响应内容。正确使用此标签可以实现灵活的页面布局控制和响应格式管理。