下面我将从 基本结构、核心标签、高级用法、实例演示 四个方面,为你全面讲解 OneThink 的列表模板。

(图片来源网络,侵删)
基本结构
一个典型的 OneThink 列表模板文件通常位于 Application/Home/View/你的控制器名/ 目录下,文件名通常为 index.html 或 list.html。
其基本结构如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">{:$title}</title> <!-- 动态获取标题 -->
<link rel="stylesheet" type="text/css" href="__PUBLIC__/css/style.css"> <!-- 引入公共CSS -->
</head>
<body>
<!-- 1. 列表页头部 -->
<div class="page-header">
<h1>{$category['title']}</h1>
<p>{$category['description']}</p>
</div>
<!-- 2. 搜索或筛选表单 (可选) -->
<div class="search-form">
<form method="get" action="{:U('你的控制器名/index')}">
<input type="text" name="keyword" placeholder="请输入关键字" value="{:I('keyword')}">
<button type="submit">搜索</button>
</form>
</div>
<!-- 3. 列表内容主体 -->
<div class="list-container">
<!-- 循环输出列表数据 -->
<volist name="list" id="vo">
<article class="list-item">
<h2><a href="{:U('你的控制器名/detail', array('id'=>$vo['id']))}">{$vo.title}</a></h2>
<div class="meta">
<span>发布时间:{:date('Y-m-d H:i:s', $vo['create_time'])}</span>
<span>浏览:{$vo.view}</span>
<span>分类:<a href="{:U('Category/index', array('id'=>$vo['category_id']))}">{$vo.category_name}</a></span>
</div>
<div class="summary">
{:htmlspecialchars_decode($vo['summary'])}
</div>
</article>
</volist>
</div>
<!-- 4. 分页导航 -->
<div class="pagination">
{$page}
</div>
</body>
</html>
核心标签与函数
理解了上面的结构,我们再来看其中最核心的几个模板标签。
变量输出
- 普通变量:
{$name}或{$Think.get.name}(获取 GET 参数)。 - 数组变量:
{$vo['title']},在<volist>循环中,id属性指定的变量名(这里是vo)就代表循环中的当前元素。 - 对象属性:
{$vo.title}($vo是一个对象)。 - 系统变量:
{:U('控制器名/方法名', 参数数组)}:最重要的函数,用于生成 URL,避免硬编码。{:U('Article/detail', array('id'=>100))}会生成类似/index.php?s=/Home/Article/detail/id/100的 URL。
{:$title}:输出由控制器分配的变量$title。{:I('get.keyword')}:安全地获取 GET/POST 参数,等同于 PHP 的I('get.keyword')。
循环标签 <volist>
这是列表页最核心的标签,用于遍历控制器传递过来的数组数据。

(图片来源网络,侵删)
<volist name="list" id="vo" empty="没有数据">
<!-- 循环体 -->
<li>ID:{$vo.id} - 标题:{$vo.title}</li>
</volist>
name="list":指定要循环的变量名,这个变量名必须和控制器中assign()的第一个参数一致。id="vo":为循环中的每个元素定义一个临时变量名,在循环体内通过$vo来访问当前元素的属性。empty="没有数据":当list数组为空时,会显示这段内容,非常实用。
分页标签 {$page}
在控制器中,我们通常会使用 Page 类进行分页查询,然后将分页生成的 HTML 代码分配给模板。
// 在控制器中
$Page = new \Think\Page($count, $pageSize); // $count是总记录数, $pageSize是每页条数
$show = $Page->show();
$this->assign('page', $show);
在模板中,直接输出 {$page} 即可,OneThink/ThinkPHP 的分页类会自动生成一套包含上一页、页码、下一页、首页、尾页的 HTML 结构。
条件判断 <if>
用于根据条件显示不同的内容。
<if condition="$vo['is_top'] eq 1">
<span class="label label-important">置顶</span>
</if>
<elseif condition="$vo['status'] eq 0"/>
<span class="label">待审核</span>
<else/>
<span class="label label-success">已发布</span>
</if>
eq:等于 (equal)neq:不等于gt:大于lt:小于egt:大于等于elt:小于等于
高级用法与最佳实践
模板继承 (Layout)
为了保持网站风格统一,OneThink 支持模板继承,你可以创建一个基础模板 Public/base.html,其他页面继承它。
Public/base.html (基础模板):
<!DOCTYPE html>
<html>
<head>
<block name="title">默认标题</block>
<block name="head"></block>
</head>
<body>
<include file="Public/header" /> <!-- 引入公共头部 -->
<block name="main-content">
<!-- 这里是默认内容,子页面可以覆盖 -->
</block>
<include file="Public/footer" /> <!-- 引入公共底部 -->
</body>
</html>
Article/index.html (继承基础模板):
<extend name="Public/base" />
<block name="title">{$category['title']} - 我的网站</block>
<block name="head">
<link rel="stylesheet" href="__PUBLIC__/css/article.css">
</block>
<block name="main-content">
<!-- 这里的内容会替换掉 base.html 中 <block name="main-content"> 的默认内容 -->
<volist name="list" id="vo">
<!-- 列表项内容 -->
</volist>
{$page}
</block>
子模板包含 `
将公共部分(如头部、底部、侧边栏)拆分成独立的模板文件,然后在需要的地方包含进来。
<include file="Public/header" /> <!-- 页面主体内容 --> <include file="Public/footer" />
处理富文本内容
文章列表通常需要显示摘要,如果摘要字段 summary 是经过 htmlspecialchars() 处理的,需要反转义才能正确显示 HTML 标签。
<div class="summary">
<!-- htmlspecialchars_decode 用于反转义HTML实体 -->
{:htmlspecialchars_decode($vo['summary'])}
</div>
完整实例演示
假设我们要实现一个文章列表页。
控制器 (Application/Home/Controller/ArticleController.class.php)
<?php
namespace Home\Controller;
use Think\Controller;
class ArticleController extends Controller {
public function index(){
// 1. 接收搜索条件
$keyword = I('keyword');
$map = array();
if($keyword){
$map['title'] = array('like', "%{$keyword}%");
}
// 2. 获取分类信息 (通常从模型获取)
$category_id = I('get.category_id', 0, 'intval');
if($category_id){
$map['category_id'] = $category_id;
}
// 3. 实例化模型并进行分页查询
$article = M('Article');
$count = $article->where($map)->count(); // 查询满足要求的总记录数
$Page = new \Think\Page($count, 10); // 每页显示10条
$show = $Page->show(); // 分页显示输出
// 进行分页数据查询 注意limit方法的参数要使用Page类的属性
$list = $article->where($map)->order('create_time DESC, id DESC')->limit($Page->firstRow.','.$Page->listRows)->select();
// 获取分类名称 (假设文章表里有category_name字段,或者通过关联查询)
// 为了演示,我们简单处理
foreach ($list as &$v) {
$v['category_name'] = M('Category')->where(array('id'=>$v['category_id']))->getField('title');
}
// 4. 分配变量到模板
$this->assign('list', $list);
$this->assign('page', $show);
$this->assign('title', '文章列表');
// 5. 渲染模板
$this->display();
}
public function detail($id){
// 详情页逻辑
$this->assign('info', M('Article')->find($id));
$this->display();
}
}
模板 (Application/Home/View/Article/index.html)
<extend name="Public/base" />
<block name="title">文章列表 - {:C('SITE_TITLE')}</block>
<block name="main-content">
<div class="container">
<h1>文章列表</h1>
<!-- 搜索框 -->
<div class="search-box">
<form action="{:U('Article/index')}" method="get">
<input type="text" name="keyword" placeholder="搜索文章..." value="{:I('keyword')}">
<button type="submit">搜索</button>
</form>
</div>
<!-- 文章列表 -->
<div class="article-list">
<volist name="list" id="vo">
<div class="article-item">
<h2><a href="{:U('Article/detail', array('id'=>$vo['id']))}">{$vo.title}</a></h2>
<div class="article-meta">
<span class="author">作者:{$vo['author']|default='匿名'}</span>
<span class="time">发布于:{:date('Y-m-d', $vo['create_time'])}</span>
<span class="category">分类:<a href="{:U('Article/index', array('category_id'=>$vo['category_id']))}">{$vo.category_name}</a></span>
<span class="views">阅读({$vo.view})</span>
</div>
<div class="article-summary">
{:htmlspecialchars_decode($vo['summary'])}
</div>
</div>
<hr>
</volist>
</div>
<!-- 分页 -->
<div class="page">
{$page}
</div>
</div>
</block>
OneThink 的列表模板开发流程可以总结为:
- 控制器端:接收参数 -> 构建查询条件 -> 使用
M()模型进行数据查询和分页 ->assign()分配数据到模板。 - 模板端:使用
<extend>继承基础布局 -> 使用<volist>循环输出数据 -> 使用{:U()}生成动态链接 -> 使用{$page}输出分页导航。
掌握这些核心标签和模式,你就可以熟练地开发出功能完善的列表页面了。
