视图页面逻辑拆分
我们在实现视图页面时,可能会遇到一个页面声明逻辑存在过于复杂的情况,也有可能存在多个页面共用一些逻辑的情况,这时我们可以将这些逻辑抽离出来,然后在视图页面按需引用进行复用。下面分别进行介绍。
zin 生成函数
为了对 zin 界面声明逻辑进行复用,可以将这些逻辑封装为函数,通常函数返回值可以为 zin 部分方法参数支持的类型(目前支持任何 php 类型,详情参考 部件 文档),函数通常命名为 buildXxxXxxx
,参数可以根据实际需要进行定义。
在函数内使用外部变量,通常不建议在视图公共函数中使用外部变量,因为会导致 zin 生成函数的复用性变差。如需使用可以使用 global $var
来引用全局变量,或通过 data()
函数来获取 zin 数据(包括 control 方法内的数据)。
下面为一个 zin 生成函数的定义:
/**
* Build project headline title
* 构建产品标题,用于页面顶部显示
*
* @param object $project
* @return mixed Any type supported by zin widget function 任何 zin 部件函数参数支持的类型
*/
function buildProjectTitle(object $project): mixed
{
return h1($project->name);
}
自定义 zin 部件方法
有时需要对一些界面声明逻辑进行复用,除了定义 zin 生成函数,还可以定义为 zin 部件方法,这样相当于自己创建了一个新的部件,可以与其他部件方法一样进行使用。
下面为一个自定义 zin 部件方法的示例:
/**
* Project list, display name and desc of project
* 产品列表,显示每个产品的名称和描述
*
* Widget props definitions 部件属性定义:
* - array items Project object list 产品对象列表
* - string title List title on top 列表标题
*
* @param mixed ...$args Any type supported by zin widget function 任何 zin 部件函数参数支持的类型
* @return mixed Any type supported by zin widget function 任何 zin 部件函数参数支持的类型
*/
function projectList(): mixed
{
/* 所有 zin 部件都可以拥有任意个参数,此时需要通过构造一个 item 来将参数转换为部件属性和子内容 */
$wg = item(func_get_args());
/* 以属性名称数组的形式定义部件支持的属性 */
$definedProps = ['items', 'title'];
/* 获取多个属性的值 */
list($items, $title) = $wg->prop($definedProps);
/* 将每个列表项对应 li 实例存储在数组内 */
$list = [];
foreach ($items as $item)
{
$list[] = li
(
strong($item->name),
span($item->desc, set::class('muted')),
);
}
/* 返回部件生成的 zin 结构 */
return ul
(
/* 将用户设置的其他属性作为 HTML 属性传递给 ul */
set($item->props->skip($definedProps)),
/* 声明列表标题 */
li(set::class('project-list-heading'), $title),
/* 直接引用列表项声明数组 */
$list,
/* 展示部件内插入的其他内容 */
$item->children()
);
}
下面为实际用法:
namespace zin;
include 'common.html.php';
$myProjects = array();
$myProjects[] = array('title' => 'hello', 'desc' => 'world');
$myProjects[] = array('title' => 'foo', 'desc' => 'bar');
$otherProjects = array();
$otherProjects[] = array('title' => 'hello others', 'desc' => 'world others');
$otherProjects[] = array('title' => 'foo others', 'desc' => 'bar others');
projectList
(
set::title('My projects'),
set::class('shadow mb-2'),
set::items($myProjects)
);
projectList
(
set::title('Other projects'),
set::items($otherProjects),
li('others projects end'),
);
render();
<ul class="shadow mb-2">
<li class="project-list-heading">My projects</li>
<li><strong>hello</strong><span class="muted">world</span></li>
<li><strong>foo</strong><span class="muted">bar</span></li>
</ul>
<ul>
<li class="project-list-heading">Other projects</li>
<li><strong>hello others</strong><span class="muted">world others</span></li>
<li><strong>foo others</strong><span class="muted">bar others</span></li>
<li>others projects end</li>
</ul>
模块下公共逻辑处理
创建 module/example/ui/common.html.php
文件,然后在此文件中定义 zin 生成方法来对公共逻辑进行封装,例如:
namespace zin;
/**
* Build project headline title
* 构建产品标题,用于页面顶部显示
*
* @param object $project
* @return mixed Any type supported by zin widget function 任何 zin 部件函数参数支持的类型
*/
function buildProjectTitle(object $project): mixed
{
return h1($project->name);
}
/**
* Build project list item, includes name and description
* 构建产品列表项,包含名称和描述
*
* @param object $project
* @return mixed Any type supported by zin widget function 任何 zin 部件函数参数支持的类型
*/
function buildProjectItem(object $project): mixed
{
return li
(
strong($project->name),
span($project->desc, set::class('muted')),
);
}
下面为在视图文件引入公共方法对示例:
namespace zin;
include 'common.html.php';
div
(
buildProjectTitle($project);
div
(
buildToolbarItem($project);
)
);
render();
namespace zin;
include 'common.html.php';
formPanel
(
to::heading(buildProjectTitle($project)),
// ...
);
render();
复杂视图的拆分
有时一个视图文件非常复杂,可能包含两个相互独立的渲染逻辑,例如产品浏览页面支持按照列表浏览也支持按照卡片浏览,这时可以将两个渲染逻辑拆分成两个视图文件,然后在主视图文件中引入这两个视图文件。我们约定将主视图文件命名为 methodname.html.php
,将拆分的视图文件命名为 methodname.*.html.php
,例如:
module/example/ui/
├── browse.html.php # 主视图文件
├── browse.list.html.php # 列表视图文件
└── browse.grid.html.php # 卡片视图文件
这样我们只需要在拆分的视图文件定义 zin 生成方法,然后在主视图文件中按需引入即可,下面为一个实际的例子:
namespace zin;
include "browse.$browseType.html.php";
buildBrowsePage();
render();
namespace zin;
/**
* Build browse page with list view
* 构建列表视图的产品浏览页面
*
* @return mixed
*/
function buildBrowsePage()
{
return dtable
(
// ...
);
}
namespace zin;
/**
* Build browse page with grid view
* 构建列表视图的产品浏览页面
*
* @return mixed
*/
function buildBrowsePage()
{
return grid
(
// ...
);
}