指令
指令是 zin 一些列内置方法,指令通常用于设置部件属性或数据以及向部件内部添加特殊内容,调用后的结果可以作为部件方法参数使用。基本使用方式为:
widget
(
directive()
);
设置属性
设置部件属性是指令最常用的用法,zin 提供了一些指令方法用于设置部件属性,包括:
方法 | 说明 | 参考 |
---|---|---|
set | 设置一个或多个属性 | 属性 |
setClass | 设置 class 属性 | 类与样式 |
setStyle | 设置 style 属性 | 类与样式 |
setCssVar | 设置 style 属性中的 CSS 变量 | 类与样式 |
setID | 设置 id 属性 | 属性 |
setTag | 设置 tagName 属性 | 属性 |
setHx | 设置 hx 属性 | 属性 |
属性的详细用法参考文档 属性,下面为一个综合的例子:
button
(
set('href', '/guide/props/'),
setClass('primary'),
setStyle('color', 'var(--btn-color)'),
setCssVar('btn-color', 'red'),
setID('myBtn'),
setTag('a')
);
<a id="myBtn" class="primary" href="/guide/props/" style="--btn-color: red; color: var(--btn-color)"></a>
定义特殊内容
指令还可以用于定义一些特殊内容并插入到页面中。下面分别进行介绍。
定义 HTML 代码
使用 html()
方法来定义 HTML,该方法定义如下:
html(string ...$codeLines): object
该方法支持任意个参数,每个参数都会当作为 HTML 代码处理,最终会将每个参数使用换行符拼接起来。下面举例说明:
div
(
html('<h1>Hello</h1>'),
html('<p>zin is awesome!</p>', '<a>Start!</a>')
);
<div>
<h1>Hello</h1>
<p>zin is awesome!</p>
<a>Start!</a>
</div>
通常不推荐使用 html()
方法直接向部件内部追加 HTML,更推荐使用部件调用来实现,上例的声明实际等价于:
div
(
h1('Hello'),
p('zin is awesome!'),
a('Start!')
);
但在以下情况使用 html()
方法是很合适的:
- HTML 来源于用户创建,例如用户通过富文本编辑器编辑的内容;
- HTML 需要灵活根据用户配置进行生成。
注意
需要谨慎处理来源于用户创建的 HTML,因为一些恶意用户提交的 HTML 被直接输出到页面可能使其他用户暴露于跨域脚本(XSS)攻击的危险中。
定义纯文本
通常我们可以向部件方法中直接传入字符串作为纯文本,但有时一些特殊部件可能会把纯文本作为他用,这时就可以通过 text()
方法来明确定义一个纯文本。该方法定义如下:
text(string ...$textLines): object
该方法支持任意个参数,每个参数都会当作为纯文本处理,最终会将每个参数使用换行符拼接起来。下面举例说明:
div
(
'Hello',
text('zin'),
icon('star'),
icon(text('star'))
);
<div>
Hello
zin,
<i class="icon icon-star"></i>
<i class="icon">star</i>
</div>
定义 HTML 元素
虽然 zin 内置了很多 HTML5 元素,但仍然无法涵盖 HTML 中的所有支持的元素,包括基于 WebComponents 实现的自定义元素以及 zin 没有内置的其他 HTML5 元素,这时可以使用指令方法 h()
来定义任意类型的 HTML 元素。该方法定义如下:
h(string $tagName, mixed ...$args): object
该方法支持任意个参数,第一个参数为 HTML 元素名称,例如 div
等,后面的所有参数都可以使用部件方法支持的任意类型。下面举例来说明:
div
(
h('em', 'zin'),
h('custom-element', '自定义 web component 元素')
);
<div>
<em>zin</em>
<custom-element>自定义 web component 元素</custom-element>
</div>
在 zin 中定义 HTML 元素实际上是创建 h
部件类实例来实现,上面的例子相当于:
div
(
new h(set('tagName', 'em'), 'zin'),
new h(set('tagName', 'custom-element'))
);
在 h
上还可以通过静态调用方法的方式来定义 HTML 元素,例如:
div
(
h::em('zin'),
h::caption('zin is awesome!')
);
<div>
<em>zin</em>
<caption>zin</caption>
</div>
定义 JS 代码
有时需要在部件内插入 JavaScript 代码,这时可以使用 js()
方法来实现。该方法定义如下:
js(string ...$codeLines): object
该方法支持任意个参数,每个参数都会当作为 JavaScript 代码处理,最终会将每个参数使用换行符拼接起来。下面举例说明:
div
(
js('const url = location.href;'),
p('zin is awesome!'),
js('console.log(`You are visiting ${url}.`);'),
);
<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
对象。例如:
js('window.hello = function() {console.log("hello")}');
定义 JS 变量
通过指令 jsVar()
方法来定义 JS 变量。该方法定义如下:
/* 一次性定义一个变量 */
jsVar(string $varName, mixed $varValue): object
/* 一次性定义多个变量 */
jsVar(array $vars): object
该方法有两种形式,一种是指定变量名称和值,一种是通过一个数组来一次新指定多个变量。变量的值会被 json_encode
处理为 JS 值。下面举例说明:
div
(
jsVar('name', 'zin'),
jsVar(array('data' => array('message' => 'awesome'), 'year' => 2023)),
jsVar('window.DEBUG', true)
);
<div></div>
<script>
(function(){
const name = 'zin';
const data = {message: 'awesome'};
const year = 2023;
}());
</script>
如果要定义全局变量,可以为变量名添加前缀 window.
,这样会在 window
对象上设置变量。例如:
div
(
jsVar('window.DEBUG', true)
);
<div></div>
<script>
(function(){
window.DEBUG = true;
}());
</script>
定义 JS 函数调用
zin 中提供了 jsCall()
来辅助生成调用 JS 函数的代码。该方法定义如下:
jsCall(string $jsFuncName, mixed ...$args): object
该方法第一个参数 $jsFuncName
为要调用的 JS 函数名,其余参数都将作为函数调用参数,jsCall()
会将每个参数通过 json_encode
转换为 JS 代码形式。下面举例说明:
$message = 'hello, zin';
$data = array('name' => 'zin');
div
(
jsCall('alert', $message);
jsCall('console.log', $data);
);
<div></div>
<script>
(function() {
alert("hello, zin");
console.log({"name": "zin"});
}());
</script>
需要注意的是使用 jsCall()
需要确保所调用的 JS 方法是存在的,否则页面运行时会出错。如果该方法调用是可以被忽略的,可以在方法名上添加后缀 ?
,这样会在生成的调用代码中插入判断该方法是否存在的代码以避免出错。例如:
div
(
jsCall('myFunc?', 42);
);
<div></div>
<script>
(function() {
if(typeof myFunc === 'function') {myFunc(42);}
}());
</script>
定义 CSS 代码
通过指令 css()
方法来定义 CSS 代码。该方法定义如下:
css(string ...$codeLines): object
该方法支持任意个参数,每个参数都会当作为 CSS 代码处理,最终会将每个参数使用换行符拼接起来。为避免样式引起界面抖动,所以会将所有通过 css()
方法添加的 CSS 代码合并通过 <style>
标签添加到输出的 HTML 头部。下面举例说明:
div
(
setClass('item'),
css('div {padding: 10px}'),
css('.item {color: red}')
);
<style>
div {padding: 10px}
.item {color: red}
</style>
<div class="item"></div>
定义 JS 和 CSS 文件导入
通过指令 import()
方法来导入 JS 或 CSS 文件。该方法定义如下:
import(string $url, ?string $type): object
该方法支持两个参数,参数 $url
为需要导入的 CSS 或 JS 文件路径,通常情况下如果被导入的文件名有明确的后缀(.css
和 .js
) 则第二个参数 $type
可以被省略,否则通过此参数指定被导入的文件类型。下面举例说明:
div
(
import('/js/zui/min.js'),
import('/js/zui/min.css'),
import('/js/zui/dtable.cjs', 'js')
);
<link rel="stylesheet" href="/js/zui/min.css">
<div></div>
<script src="/js/zui/min.js"></script>
提示
为避免 JS 文件阻塞渲染以及 CSS 文件造成界面抖动,JS 文件导入会输出到 HTML 代码最后,但会在通过 js
和 jsVar
方法生成的 JS 代码之前,CSS 文件导入会输出到 HTML 前面,并且在所有自定义 CSS 代码之前。
设置块内容
通常向部件内部传递的子内容会被部件一起进行处理,但有时一些自定义部件允许用户设置不同区块内的子内容,这时就可以通过设置内部块的形式实现。关于内部块的更多说明参考 内部块。
一般使用
通过指令 to()
方法来设置部件指定内部块的内容。该方法定义如下:
to(string $blockName, mixed ...$args): object
其中参数 $blockName
为要设置的块名称,其余参数为要添加到该快内部的内容。下面举例说明:
page
(
to('head', css('body {font-size: 12px}')),
css('h1 {font-size: 32px}'),
h1('Hello, zin')
);
<!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
上提供了静态方法来插入内容到指定的内部块,其中方法名即为块名称。上面的例子使用静态方法的方式为:
page
(
to::head(css('body {font-size: 12px}')),
css('h1 {font-size: 32px}'),
h1('Hello, zin')
);
设置页面数据
🚧 此部分功能正在完善
设置部件数据 WIP
🚧 此部分功能正在完善