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

onethink 列表模板
(图片来源网络,侵删)

基本结构

一个典型的 OneThink 列表模板文件通常位于 Application/Home/View/你的控制器名/ 目录下,文件名通常为 index.htmllist.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>

这是列表页最核心的标签,用于遍历控制器传递过来的数组数据。

onethink 列表模板
(图片来源网络,侵删)
<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 的列表模板开发流程可以总结为:

  1. 控制器端:接收参数 -> 构建查询条件 -> 使用 M() 模型进行数据查询和分页 -> assign() 分配数据到模板。
  2. 模板端:使用 <extend> 继承基础布局 -> 使用 <volist> 循环输出数据 -> 使用 {:U()} 生成动态链接 -> 使用 {$page} 输出分页导航。

掌握这些核心标签和模式,你就可以熟练地开发出功能完善的列表页面了。