YOOtheme Pro教程 - 元素
自定义元素是扩展 YOOtheme Pro 页面生成器(Page Builder)功能的最简单方法。 复制现有元素并自定义其标记和设置,或从头开始创建新的元素。
可以使用子主题或Joomla插件将自定义元素添加到页面构建器。添加元素的最简单方法是使用子主题。这通常用于客户项目(现有网站项目)。为YOOtheme Pro开发第三方扩展时应使用Joomla插件。查看Yootheme官网扩展页面,了解开发人员为YOOtheme Pro开发的第三方插件。
#入门
最简单的入门方法是试用示例元素或查看包含的YOOtheme Pro元素。将元素添加到页面构建器后,它将出现在元素库中的Custom
组下。
示例元素
GitHub 上的示例元素演示了如何配置元素、扩展其功能以及使用不同的字段类型。 只需下载并解压缩该元素。 最快的尝试方法是使用子主题。
下载 | 查看Github项目
包含的元素
在YOOtheme Pro
的vendor/yootheme
下的相应模块目录中找到包含的元素(系统自带的元素)。
目录 | 元素 |
---|---|
builder/elements |
accordion, alert, button, code, column, countdown, description_list, divider, gallery, grid, headline, html, icon, image, layout, list, map, overlay, panel, popover, quotation, row, section, slider, slideshow, social, subnav, switcher, table, text, totop, video |
builder-newsletter/elements |
newsletter |
builder-joomla/elements |
breadcrumbs, module, module_position |
builder-wordpress/elements |
breadcrumbs, module, module_position |
builder-joomla-source/elements |
pagination |
builder-wordpress-source/elements |
comments, pagination |
如果希望通过定制现有元素来创建新元素,只需复制其中一个包含的元素并修改它的element.json文件
为其指定一个唯一名称。
#文档结构
元素有自己的目录,其中包含配置文件和模板文件。
文件 | 描述 |
---|---|
element.json |
定义元素配置、字段和设置。 |
element.php |
使用自定义转换或更新功能扩展元素功能。该文件是可选的,必须通过element.json 导入。 |
templates/template.php |
渲染元素布局。 渲染通常被拆分为以template- 为前缀的模板部分。 |
templates/content.php |
直接输出元素内容而去除布局标记。 内容保存在Joomla页面中。 它供Joomla搜索使用,并在停用YOOtheme Pro时保留于Joomla的文章内容。 |
images/icon.svg |
元素库中显示的图标 |
images/iconSmall.svg |
页面生成器中显示的图标 |
#JSON配置
element.json
定义了元素的名称、图标、字段以及在页面生成器的编辑界面。确保设置不被现有元素采用的唯一元素名称,例如 my_element。以下示例显示了一个没有任何字段的简单元素配置。
{
"name": "example",
"title": "Example",
"icon": "${url:images/icon.svg}",
"iconSmall": "${url:images/iconSmall.svg}",
"element": true,
"width": 500,
"templates": {
"render": "./templates/template.php",
"content": "./templates/content.php"
}
}
属性 | 描述 |
---|---|
name |
元素的名称,值必须是唯一。 |
title |
页面生成器中显示的元素名称 |
icon |
元素库中使用的图标的路径 |
iconSmall |
页面生成器中使用的图标的路径 |
element |
显示元素库中的元素。 |
width |
编辑元素时定制器侧边栏的宽度 |
templates |
两个所需模板文件的路径 |
组(group)属性
默认情况下,自定义元素会自动分配在元素库中Custom
组下。要为元素创建专用组,请设置group
属性。如果元素在不同项目之间共用或在为YOOtheme Pro开发第三方扩展时,建议这样做。
"group": "my company"
#字段(fields)
元素的字段可以在element.json
文件的fields对象中定义。只需添加一个字段名称及其字段定义。
"fields": {
"my_field": {}
}
此外,在页面构建器中编辑元素时,设置默认字段集对象中的所有字段以定义它们的顺序和布局。
"fieldset": {
"default": {
"fields": [
"my_field"
]
}
}
属性
每个字段都由其类型和其他属性定义。 以下属性适用于所有字段类型。
属性 | 描述 |
---|---|
name |
字段的名称。 未设置时,从对象属性键推断。 |
type |
设置字段输入类型,默认情况下,它是文本类型。 |
label |
在字段上方显示字段的名称。 |
description |
在字段下方显示字段说明。 |
attrs |
向呈现的字段添加额外的HTML属性。 |
show |
仅当满足特定条件时才显示字段。 |
enable |
仅在满足特定条件时启用字段。 |
在以下示例中,显示了一个名为 Content 的输入字段。
"fields": {
"content": {
"label": "Content",
"description": "A description text.",
"attrs": {
"placeholder": "Enter text"
}
}
},
"fieldset": {
"default": {
"fields": [
"content"
]
}
}
在以下示例中,只有在填写content
字段时才能选择样式选项。 只有填写了content
字段并且style
设置为primary
时,才会显示图标选择器。
"fields": {
"content": {
"label": "Content"
},
"style": {
"label": "Style",
"type": "select",
"options": {
"None": "",
"Primary": "primary",
"Secondary": "secondary"
},
"enable": "content"
},
"icon": {
"label": "Icon",
"type": "icon",
"show": "content && style=='primary'"
}
},
"fieldset": {
"default": {
"fields": [
"content",
"style",
"icon"
]
}
}
选项卡(tabs)
这是可选项。将fieldset
对象类型设置为tabs
,使字段以选项卡的形式呈现。 以下示例有两个选项卡 - Content
和Settings
。 选项卡中的Content
显示内容字段,选项卡中的Settings
显示两个选项字段。
"fields": {
"content": {
"label": "Content"
},
"option_a": {
"label": "Select",
"type": "select",
"options": {
"Option 1": 0,
"Option 2": 1,
"Option 3": 2
}
},
"option_b": {
"label": "Checkbox",
"type": "checkbox",
"text": "Some text"
}
},
"fieldset": {
"default": {
"type": "tabs",
"fields": [
{
"title": "Content",
"fields": [
"content"
]
},
{
"title": "Settings",
"fields": [
"option_a",
"option_b"
]
}
]
}
}
默认值
将元素添加到页面生成器时,可以将字段设置为默认值。只需在element.json
文件中的defaults
对象中将字段键设置为默认值。在以下示例中,文本字段content
将使用Some default value
填充。
"defaults": {
"content": "Some default value."
},
"fields": {
"content": {
"label": "Content",
"type": "textarea",
"attrs": {
"rows": 6
}
}
},
"fieldset": {
"default": {
"fields": [
"content"
]
}
}
预览占位符(Preview Placeholder)
字段即使没有内容,也可以在页面生成器的预览区域中显示占位符。填写完字段内容后,占位符消失,并显示字段值。只需修改element.json
文件中的placeholder
下的props
并设置其字段值。在以下示例中,只要未填写内容字段,该元素就会显示“Lorem ipsum ...”占位符文本。
"placeholder": {
"props": {
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
}
},
"fields": {
"content": {
"label": "Content",
"type": "textarea",
"attrs": {
"rows": 6
}
}
},
"fieldset": {
"default": {
"fields": [
"content"
]
}
}
插值语法
YOOtheme Pro带有强大的插值语法来引用值和调用函数。这些插值嵌入在字符串中并包裹在${}
中,例如${var.foo}
。
例如,这用于一般元素设置,这些设置通常在元素之间是相同的。这些字段在vendor/yootheme/builder/config/builder.json
文件中定义。它们的字段定义可以引用为${builder.NAME}
。以下示例将字段名称maxwidth
设置为builder.json
文件中定义的字段定义。
"fields": {
"maxwidth": "${builder.maxwidth}"
},
"fieldset": {
"default": {
"fields": [
"maxwidth"
]
}
}
这是builder.json
文件中引用的字段定义。
"maxwidth": {
"label": "Max Width",
"description": "Set the maximum content width.",
"type": "select",
"options": {
"None": "",
"Small": "small",
"Medium": "medium",
"Large": "large",
"X-Large": "xlarge",
"2X-Large": "2xlarge"
}
}
另一个示例是高级设置选项卡,它在所有元素中也是相同的。 这些字段的顺序和布局也从builder.json
文件中引用。
"fields": {
"content": {
"label": "Content",
"type": "textarea"
},
"name": "${builder.name}",
"source": "${builder.source}",
"id": "${builder.id}",
"status": "${builder.status}",
"class": "${builder.cls}",
"attributes": "${builder.attrs}",
"css": {
"type": "editor",
"label": "CSS",
"description": "Enter your own custom CSS.",
"editor": "code",
"mode": "css",
"attrs": {
"debounce": 500
}
}
},
"fieldset": {
"default": {
"type": "tabs",
"fields": [
{
"title": "Content",
"fields": [
"content"
]
},
"${builder.advanced}"
]
}
}
这是builder.json
文件中的引用值。
"advanced": {
"title": "Advanced",
"fields": [
"name",
"status",
"source",
"id",
"class",
"attributes",
"css"
]
}
动态内容(Dynamic Content)
要添加允许选择内容源的dynamic content
字段,请从builder.json
文件中引用source
字段。 如上例所示,引用高级设置选项卡也定义了内容源字段(source field)。
"fields": {
"source": "${builder.source}"
},
"fieldset": {
"default": {
"fields": [
"source"
]
}
}
要允许字段映射动态内容,请将字段source
属性设置为true
。
"fields": {
"content": {
"label": "Content",
"description": "A text field that can be mapped to a field of a content source.",
"source": true
}
}
#字段类型(Field Types)
这是YOOtheme Pro中所有可用内容字段类型(Field Types)的列表。
名称 | 描述 |
---|---|
checkbox |
定义一个复选框。 |
color |
定义一个颜色选择器。 |
editor |
定义一个可视化和代码编辑器。 |
font |
定义一个字体选择器。 |
icon |
为UIkit图标库定义一个图标选择器。 |
image |
为媒体库中的文件定义一个图像选择器。 |
link |
为Joomla系统链接和媒体库文件定义链接选择器。 |
location |
定义交互式地图来选择位置。 |
number |
定义一个数字输入字段。 |
radio |
定义一组单选按钮。 |
range |
定义一个带有附加输入字段的范围滑块。 |
select |
定义一个选择框。 |
text |
定义单行文本输入字段。 |
textarea |
为多行文本定义一个纯文本区域。 |
video |
为媒体库中的文件定义视频选择器。 |
具有附加属性的字段类型如下所述。
复选框字段(Checkbox Field)
复选框字段有一个附加属性 text
来设置复选框旁边的文本。
{
"label": "Checkbox",
"type": "checkbox",
"text": "The text next to the checkbox."
}
编辑器字段有一个editor
属性,当设置为 code
时仅加载代码编辑器。 附加的mode
属性明确定义了代码语言css
、js
或text/html
。
以下示例显示了一个带有Visual
和Code
选项卡的编辑器。
{
"label": "Editor",
"type": "editor"
}
以下示例仅显示了带有 CSS 语法突出显示的代码编辑器。
{
"label": "Code Editor",
"type": "editor",
"editor": "code",
"mode": "css",
"attrs": {
"debounce": 500
}
}
注意 要防止在编辑器中输入时更新定制器预览,请将debounce
属性设置为大约500
毫秒。
选择字段(Select Field)
选择字段的选项和默认值具有options
和default
属性。
{
"label": "Select",
"type": "select",
"default": 0,
"options": {
"Option 1": 0,
"Option 2": 1,
"Option 3": 2
}
}
单选字段(Radio Field)
单选字段具有name
、options
和default
属性,分别设置名称、选项和默认选项的值。
{
"label": "Radio",
"type": "radio",
"name": "radio_group",
"default": 0,
"options": {
"Option 1": 0,
"Option 2": 1,
"Option 3": 2
}
}
范围滑块字段(Range Field)
范围滑块字段(Range Field)没有额外的属性,但需要设置min
、max
和step
这几项HTML属性。
{
"label": "Range",
"type": "range",
"attrs": {
"min": 1,
"max": 10,
"step": 0.5
}
}
#字段布局(Field Layouts)
某些字段类型仅用于在页面构建器中对字段进行布局,本身没有内容。 它们通常用在fieldset
对象中。 包含字段在fields
对象中定义。
名称 | 描述 |
---|---|
grid |
在网格中排列共享下面的描述文本的字段。 |
group |
使用标签和控件并排紧凑地排列字段,并将描述文本作为工具提示。 |
网格字段(Grid Field)
网格字段有一个width
属性来定义每个网格单元格的宽度。
"fields": {
"image": {
"label": "Image",
"type": "image"
},
"width": {
"label": "Width"
},
"height": {
"label": "Height"
}
},
"fieldset": {
"default": {
"fields": [
"image",
{
"description": "A description text below the grid.",
"type": "grid",
"name": "_image_dimension",
"width": "1-2",
"fields": [
"width",
"height"
]
}
]
}
}
注意 fieldset
对象中的内联字段定义需要唯一的名称。 默认情况下,label
属性用作名称的后备。 但是如果字段定义没有上例中的标签,则必须设置唯一的name
。 我们用 _ 前缀标记未在任何地方使用的名称。
组字段(Group Field)
组字段(Group Field)有一个divider
属性,用来在组的底部设置一个分隔符。
"fields": {
"content": {
"label": "Content"
},
"option_a": {
"label": "Select",
"type": "select",
"options": {
"Option 1": 0,
"Option 2": 1,
"Option 3": 2
}
},
"option_b": {
"label": "Checkbox",
"type": "checkbox",
"text": "Some text"
},
"option_c": {
"label": "Text"
}
},
"fieldset": {
"default": {
"fields": [
"content",
{
"label": "Group 1",
"type": "group",
"divider": true,
"fields": [
"option_a",
"option_b"
]
},
{
"label": "Group 2",
"type": "group",
"fields": [
"option_a",
"option_b"
]
}
]
}
}
注意 与网格字段不同,组字段通常有一个label
属性,这就是为什么不需要设置name
的原因。
#模板文件
在模板中渲染元素节点时,可以使用以下变量。
名称 | 描述 |
---|---|
$node |
元素节点(stdClass) |
$props |
元素属性$node->props 使用字段(array) 设置 |
$children |
$children子元素$node->children ,例如包含多个item元素的items的(array) |
$builder |
当前用于渲染子节点的生成器实例 (YOOtheme\Builder) |
字段属性(Field Properties)
veelement.json
文件中定义的所有元素字段都可以使用$props
变量作为属性进行访问。 它们的类型由字段类型定义,如果用户尚未输入值,则为null
。
<?php
// Properties
$props['option_a']; // String
$props['option_b']; // Integer
$props['option_c']; // Boolean
?>
<?php if ($props['title']) : ?>
<h3><?= $props['title'] ?></h3>
<?php endif ?>
<?php if ($props['content']) : ?>
<div><?= $props['content'] ?></div>
<?php endif ?>
模板零件
渲染元素布局通常使用辅助函数$this->render()
拆分为以template-
为前缀的模板零件。 以下示例呈现template-content.php
文件并传递元素属性$props
。
<?= $this->render("{$__dir}/template-content", compact('props')) ?>
模板引擎
YOOtheme Pro模板引擎提供了一个HTML帮助函数$this->el()
来使用$props
变量的紧凑插值语法创建 HTML元素。 它还可以轻松合并属性。
语法 | 描述 |
---|---|
foo-{bar} |
如果$props['bar'] 有值,则添加foo-{bar} 并将{bar} 替换为该值。 |
foo {@bar} |
如果$props['bar'] 有值,则添加foo 。 |
foo {@!bar} |
如果$props['bar'] 没有值,则添加foo 。 |
foo {@bar: value} |
如果$props['bar'] 设置为value ,则添加foo 。 |
foo {@bar: value1|value2} |
如果$props['bar'] 设置为value1 或value2 ,则添加foo 。 |
foobar [foo {@bar}] |
添加foobar 并可选择添加foo 如果$props['bar'] 有值。 |
<?php
//创建包裹元素容器
$el = $this->el('div', [
'class' => [
//如果样式有值,则添加两个类
'uk-card uk-card-{style}',
//如果样式没有值,则添加一个类
'uk-panel {@!style}',
//如果style有值则添加两个类,如果size也有值则添加另一个类
'uk-card uk-card-{style} [uk-card-{size}]',
],
'style' => [
//如果min-height有值则为其赋值
'min-height: {min_height}px',
],
// 添加HTML属性`uk-grid`
'uk-grid' => true,
]);
// 创建包裹内容容器
$content = $this->el('div', [
'class' => [
//如果样式有值则为其添加对应类
'uk-card-body {@style}',
// 如果边距大小有值,则添加类似`uk-margin-small`的大小类,否则仅添加`uk-margin`
'uk-margin[-{margin_size}]',
],
]);
?>
<?= $el($props, $attrs) // 开始渲染HTML标签 ?>
<?php if ($props['content']) : ?>
<?= $content($props, $props['content']) // 渲染整个HTML的元素 ?>
<?php endif ?>
<?= $el->end() // 结束渲染HTML标签 ?>
有几个参数传递给 HTML 元素渲染。
实参(ARGUMENT) | 类型 | 描述 |
---|---|---|
$params | array |
传递所需的元素属性$props 。 |
$attrs | array |
(可选)传递其他属性以合并它们。 常规和高级元素设置所需的属性存储在attrs 变量中,并应传递给包裹在HTML代码的元素。 |
$contents | mixed |
可选地,传递任何内容,例如 $props['content'],整个HTML元素将被渲染。 |
#转换和更新
可选的element.php
文件通过自定义转换或更新函数扩展元素功能。 它必须通过 element.json
文件引入。
{
"@import": "./element.php",
"name": "example",
"title": "Example",
"icon": "${url:images/icon.svg}",
"iconSmall": "${url:images/iconSmall.svg}",
"element": true,
"width": 500,
"templates": {
"render": "./templates/template.php",
"content": "./templates/content.php"
}
}
这是一个关于如何为元素节点定义转换和更新的示例。 它还显示可用的对象和参数。
<?php
return [
// Define transforms for the element node
'transforms' => [
// The function is executed before the template is rendered
'render' => function ($node, array $params) {
// Element object (stdClass)
$node->type; // Type name (string)
$node->props; // Field properties (array)
$node->children; // All children (array)
// Parameter array
$params['path']; // All parent elements (array)
$params['parent']; // Parent element (stdClass)
$params['builder']; // Builder instance (YOOtheme\Builder)
$params['type']; // Element definition (YOOtheme\Builder\ElementType)
},
],
// Define updates for the element node
'updates' => [
// 如果保存元素时的YOOtheme Pro版本小于当前版本,则执行该函数。
'1.18.0' => function ($node, array $params) {
},
],
];
折叠布局
如果元素的内容字段为空,为了防止元素呈现,采取联动的折叠布局。
return [
'transforms' => [
'render' => function ($node) {
// Don't render the element if the title or content field is empty
return $node->props['title'] || $node->props['content'];
},
],
];
请注意,对于单个内容字段,返回值必须转换为布尔值。
return [
'transforms' => [
'render' => function ($node) {
// Don't render element if the content field is empty
return (bool) $node->props['content'];
},
],
];
更新
为新版本的 YOOtheme Pro 定义元素更新。
return [
'updates' => [
'2.1.0-beta.1' => function ($node) {
// Rename a field value
if (@$node->props['width'] === 'xxlarge') {
$node->props['width'] = '2xlarge';
}
},
'1.20.2' => function ($node) {
// Rename a field key
if (isset($node->props['breakpoint'])) {
$node->props['grid_breakpoint'] = $node->props['breakpoint'];
unset($node->props['breakpoint']);
}
},
],
];
注意 当前元素更新与 YOOtheme Pro 的更新相关联。 它们没有自己的版本号,只能在 YOOtheme Pro 版本号更改时更新。
内容项目
具有内容项的元素,如Grid元素,是包含子元素的父元素。要创建父元素,请将element.json
文件中的container
属性设置为 true
。 要添加一个显示管理content items
界面的字段,请使用content-items
字段类型并将item
属性设置为子元素的name
。
{
"name": "example",
"title": "Example",
"icon": "${url:images/icon.svg}",
"iconSmall": "${url:images/iconSmall.svg}",
"element": true,
"container": true,
"width": 500,
"templates": {
"render": "./templates/template.php",
"content": "./templates/content.php"
},
"fields": {
"content": {
"label": "Items",
"type": "content-items",
"item": "example_item"
}
},
"fieldset": {
"default": {
"fields": [
"content"
]
}
}
}
就像任何其他元素一样,子元素具有自己的目录、具有唯一元素名称和模板文件的 JSON 配置。 它没有显示在元素库中,这就是它也没有图标的原因。 通常,子元素还具有一个高级设置选项卡,该选项卡在所有子元素中都是相同的。 它的字段 order 和 layout 是从builder.json
文件中引用的。
{
"name": "example_item",
"title": "Item",
"width": 500,
"templates": {
"render": "./templates/template.php",
"content": "./templates/content.php"
},
"fields": {
"title": {
"label": "Title",
"source": true
},
"content": {
"label": "Content",
"type": "editor",
"source": true
},
"image": {
"label": "Image",
"type": "image",
"source": true
},
"status": "${builder.statusItem}",
"source": "${builder.source}"
},
"fieldset": {
"default": {
"type": "tabs",
"fields": [
{
"title": "Content",
"fields": [
"title",
"content",
"image"
]
},
"${builder.advancedItem}"
]
}
}
}
子元素应该至少有一个title
字段和一个可选的image
字段。 两者都将显示在由父元素中的content-items
字段创建的内容项列表中。
模板文件
所有子元素都可以通过 $children
数组访问并使用辅助函数 $builder->render()
进行渲染。
<?php foreach ($children as $child) : ?>
<?= $builder->render($child, ['element' => $props]) ?>
<?php endforeach ?>
通常,父元素的$props
变量作为$element
传递给子元素,因此父元素的所有字段都可以访问模板文件中的子元素。
<?php
// Property of the parent element
$element['option_a'];
?>
添加媒体按钮
默认情况下,content-items
字段会显示一个AddItem
按钮来创建新的内容项。或者,添加一个AddMedia
按钮,该按钮允许在媒体管理器中选择图像。对于每个选定的图像,都会创建一个新项目。image
和title
字段会自动填写。
只需定义media
对象并将其type
属性设置为image
。使用item
对象定义图像title
和src
设置到哪些字段。
"fields": {
"content": {
"label": "Items",
"type": "content-items",
"item": "example_item",
"media": {
"type": "image",
"item": {"title": "title", "image": "src"}
}
}
},
"fieldset": {
"default": {
"fields": [
"content"
]
}
}
预览占位符
元素可以在页面构建器预览中显示占位符项目,而它们没有内容项目。 添加内容项后,placeholder
项将消失,并显示内容项。 只需在element.json
文件中的children
下的占位符对象中设置占位符项。通过将type
属性设置为子元素的name
来为每个占位符项创建一个对象。
"placeholder": {
"children": [
{"type": "example_item", "props": {}},
{"type": "example_item", "props": {}},
{"type": "example_item", "props": {}}
]
},
"fields": {
"content": {
"label": "Items",
"type": "content-items",
"item": "example_item"
}
},
"fieldset": {
"default": {
"fields": [
"content"
]
}
}
请确保在子元素中定义占位符。
"placeholder": {
"props": {
"title": "Title",
"content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
}
}
如有需要,也可以在props
对象中为占位符项的字段设置不同的占位符值。
"placeholder": {
"children": [
{"type": "example_item", "props": {"position_x": 20, "position_y": 50}},
{"type": "example_item", "props": {"position_x": 50, "position_y": 20}},
{"type": "example_item", "props": {"position_x": 70, "position_y": 70}}
]
}