Skip to content

指令

指令是 zin 一些列内置方法,指令通常用于设置部件属性或数据以及向部件内部添加特殊内容,调用后的结果可以作为部件方法参数使用。基本使用方式为:

php
widget
(
    directive()
);

设置属性

设置部件属性是指令最常用的用法,zin 提供了一些指令方法用于设置部件属性,包括:

方法说明参考
set设置一个或多个属性属性
setClass设置 class 属性类与样式
setStyle设置 style 属性类与样式
setCssVar设置 style 属性中的 CSS 变量类与样式
setID设置 id 属性属性
setTag设置 tagName 属性属性
setHx设置 hx 属性属性

属性的详细用法参考文档 属性,下面为一个综合的例子:

php
button
(
    set('href', '/guide/props/'),
    setClass('primary'),
    setStyle('color', 'var(--btn-color)'),
    setCssVar('btn-color', 'red'),
    setID('myBtn'),
    setTag('a')
);
html
<a id="myBtn" class="primary" href="/guide/props/" style="--btn-color: red; color: var(--btn-color)"></a>

定义特殊内容

指令还可以用于定义一些特殊内容并插入到页面中。下面分别进行介绍。

定义 HTML 代码

使用 html() 方法来定义 HTML,该方法定义如下:

php
html(string ...$codeLines): object

该方法支持任意个参数,每个参数都会当作为 HTML 代码处理,最终会将每个参数使用换行符拼接起来。下面举例说明:

php
div
(
    html('<h1>Hello</h1>'),
    html('<p>zin is awesome!</p>', '<a>Start!</a>')
);
html
<div>
  <h1>Hello</h1>
  <p>zin is awesome!</p>
  <a>Start!</a>
</div>

通常不推荐使用 html() 方法直接向部件内部追加 HTML,更推荐使用部件调用来实现,上例的声明实际等价于:

php
div
(
    h1('Hello'),
    p('zin is awesome!'),
    a('Start!')
);

但在以下情况使用 html() 方法是很合适的:

  • HTML 来源于用户创建,例如用户通过富文本编辑器编辑的内容;
  • HTML 需要灵活根据用户配置进行生成。

注意

需要谨慎处理来源于用户创建的 HTML,因为一些恶意用户提交的 HTML 被直接输出到页面可能使其他用户暴露于跨域脚本(XSS)攻击的危险中。

定义纯文本

通常我们可以向部件方法中直接传入字符串作为纯文本,但有时一些特殊部件可能会把纯文本作为他用,这时就可以通过 text() 方法来明确定义一个纯文本。该方法定义如下:

php
text(string ...$textLines): object

该方法支持任意个参数,每个参数都会当作为纯文本处理,最终会将每个参数使用换行符拼接起来。下面举例说明:

php
div
(
    'Hello',
    text('zin'),
    icon('star'),
    icon(text('star'))
);
html
<div>
  Hello
  zin,
  <i class="icon icon-star"></i>
  <i class="icon">star</i>
</div>

定义 HTML 元素

虽然 zin 内置了很多 HTML5 元素,但仍然无法涵盖 HTML 中的所有支持的元素,包括基于 WebComponents 实现的自定义元素以及 zin 没有内置的其他 HTML5 元素,这时可以使用指令方法 h() 来定义任意类型的 HTML 元素。该方法定义如下:

php
h(string $tagName, mixed ...$args): object

该方法支持任意个参数,第一个参数为 HTML 元素名称,例如 div 等,后面的所有参数都可以使用部件方法支持的任意类型。下面举例来说明:

php
div
(
    h('em', 'zin'),
    h('custom-element', '自定义 web component 元素')
);
html
<div>
  <em>zin</em>
  <custom-element>自定义 web component 元素</custom-element>
</div>

在 zin 中定义 HTML 元素实际上是创建 h 部件类实例来实现,上面的例子相当于:

php
div
(
    new h(set('tagName', 'em'), 'zin'),
    new h(set('tagName', 'custom-element'))
);

h 上还可以通过静态调用方法的方式来定义 HTML 元素,例如:

php
div
(
    h::em('zin'),
    h::caption('zin is awesome!')
);
html
<div>
  <em>zin</em>
  <caption>zin</caption>
</div>

定义 JS 代码

有时需要在部件内插入 JavaScript 代码,这时可以使用 js() 方法来实现。该方法定义如下:

php
js(string ...$codeLines): object

该方法支持任意个参数,每个参数都会当作为 JavaScript 代码处理,最终会将每个参数使用换行符拼接起来。下面举例说明:

php
div
(
    js('const url = location.href;'),
    p('zin is awesome!'),
    js('console.log(`You are visiting ${url}.`);'),
);
html
<div>
  <p>zin is awesome!</p>
</div>
<script>
(function() {
    const url = location.href;
    console.log(`You are visiting ${url}.`);
}());
</script>

需要注意在同一个部件内部通过 js() 方法添加的所有 JavaScript 代码会通过换行符拼接起来,并放在在一个立即执行表达式(IIFE)中,最后将代码通过 <script> 元素输出到部件最终 HTML 的末尾。采用上述规则的原因是:

  • 将代码放在立即执行表达式中可以让我们的 JavaScript 代码运行在一个独立的作用域中,从而避免污染全局作用域;
  • 将 JavaScript 代码尽量放置在文档末尾不会阻止页面边加载边呈现,尽量减少 JavaScript 代码对文档渲染的影响。

提示

因为你的 JS 代码是在独立的作用域中,如果你想定义全局变量或方法,可以将变量和方法赋值给 window 对象。例如:

php
js('window.hello = function() {console.log("hello")}');

定义 JS 变量

通过指令 jsVar() 方法来定义 JS 变量。该方法定义如下:

php
/* 一次性定义一个变量 */
jsVar(string $varName, mixed $varValue): object

/* 一次性定义多个变量 */
jsVar(array $vars): object

该方法有两种形式,一种是指定变量名称和值,一种是通过一个数组来一次新指定多个变量。变量的值会被 json_encode 处理为 JS 值。下面举例说明:

php
div
(
    jsVar('name', 'zin'),
    jsVar(array('data' => array('message' => 'awesome'), 'year' => 2023)),
    jsVar('window.DEBUG', true)
);
html
<div></div>
<script>
(function(){
    const name = 'zin';
    const data = {message: 'awesome'};
    const year = 2023;
}());
</script>

如果要定义全局变量,可以为变量名添加前缀 window.,这样会在 window 对象上设置变量。例如:

php
div
(
    jsVar('window.DEBUG', true)
);
html
<div></div>
<script>
(function(){
    window.DEBUG = true;
}());
</script>

定义 JS 函数调用

zin 中提供了 jsCall() 来辅助生成调用 JS 函数的代码。该方法定义如下:

php
jsCall(string $jsFuncName, mixed ...$args): object

该方法第一个参数 $jsFuncName 为要调用的 JS 函数名,其余参数都将作为函数调用参数,jsCall() 会将每个参数通过 json_encode 转换为 JS 代码形式。下面举例说明:

php
$message = 'hello, zin';
$data    = array('name' => 'zin');

div
(
    jsCall('alert', $message);
    jsCall('console.log', $data);
);
html
<div></div>
<script>
(function() {
    alert("hello, zin");
    console.log({"name": "zin"});
}());
</script>

需要注意的是使用 jsCall() 需要确保所调用的 JS 方法是存在的,否则页面运行时会出错。如果该方法调用是可以被忽略的,可以在方法名上添加后缀 ?,这样会在生成的调用代码中插入判断该方法是否存在的代码以避免出错。例如:

php
div
(
    jsCall('myFunc?', 42);
);
html
<div></div>
<script>
(function() {
    if(typeof myFunc === 'function') {myFunc(42);}
}());
</script>

定义 CSS 代码

通过指令 css() 方法来定义 CSS 代码。该方法定义如下:

php
css(string ...$codeLines): object

该方法支持任意个参数,每个参数都会当作为 CSS 代码处理,最终会将每个参数使用换行符拼接起来。为避免样式引起界面抖动,所以会将所有通过 css() 方法添加的 CSS 代码合并通过 <style> 标签添加到输出的 HTML 头部。下面举例说明:

php
div
(
    setClass('item'),
    css('div {padding: 10px}'),
    css('.item {color: red}')
);
html
<style>
  div {padding: 10px}
  .item {color: red}
</style>
<div class="item"></div>

定义 JS 和 CSS 文件导入

通过指令 import() 方法来导入 JS 或 CSS 文件。该方法定义如下:

php
import(string $url, ?string $type): object

该方法支持两个参数,参数 $url 为需要导入的 CSS 或 JS 文件路径,通常情况下如果被导入的文件名有明确的后缀(.css.js) 则第二个参数 $type 可以被省略,否则通过此参数指定被导入的文件类型。下面举例说明:

php
div
(
    import('/js/zui/min.js'),
    import('/js/zui/min.css'),
    import('/js/zui/dtable.cjs', 'js')
);
html
<link rel="stylesheet" href="/js/zui/min.css">
<div></div>
<script src="/js/zui/min.js"></script>

提示

为避免 JS 文件阻塞渲染以及 CSS 文件造成界面抖动,JS 文件导入会输出到 HTML 代码最后,但会在通过 jsjsVar 方法生成的 JS 代码之前,CSS 文件导入会输出到 HTML 前面,并且在所有自定义 CSS 代码之前。

设置块内容

通常向部件内部传递的子内容会被部件一起进行处理,但有时一些自定义部件允许用户设置不同区块内的子内容,这时就可以通过设置内部块的形式实现。关于内部块的更多说明参考 内部块

一般使用

通过指令 to() 方法来设置部件指定内部块的内容。该方法定义如下:

php
to(string $blockName, mixed ...$args): object

其中参数 $blockName 为要设置的块名称,其余参数为要添加到该快内部的内容。下面举例说明:

php
page
(
   to('head', css('body {font-size: 12px}')),
   css('h1 {font-size: 32px}'),
   h1('Hello, zin')
);
html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="renderer" content="webkit">
  <style>body {font-size: 12px}</style>
</head>
<body>
  <style>h1 {font-size: 32px}</style>
  <h1>Hello, zin</h1>
</body>
</html>

在上面的例子中使用了两次 css() 调用,第一次是作为 to() 指令参数,将指定的 CSS 样式通过 <style> 元素插入到 <head> 元素内部,第二次直接作为 page() 部件方法参数,将 CSS 样式插入到了 <body> 元素内部。之所以能够实现上述功能是因为 page() 部件定义了一个内部块,名称为 head,这样可以方便的将内容明确插入到 HTML 头部。

静态方法

在 zin 中还在静态类 to 上提供了静态方法来插入内容到指定的内部块,其中方法名即为块名称。上面的例子使用静态方法的方式为:

php
page
(
   to::head(css('body {font-size: 12px}')),
   css('h1 {font-size: 32px}'),
   h1('Hello, zin')
);

设置页面数据

🚧 此部分功能正在完善

设置部件数据 WIP

🚧 此部分功能正在完善

https://zentao.net