webino / webino-draw
Zend Framework 2 的 XHTML 布局渲染器
Requires
- php: >=5.3.3
- zendframework/zendframework: 2.*
Suggests
- webino/ZF2NetteDebug: User friendly Exception and Error handler ported from Nette Framework.
This package is auto-updated.
Last update: 2024-08-29 03:26:13 UTC
README
提供配置布局渲染的能力。 仍在开发中,仅供娱乐使用。
特性
- 自动转义
- Ajax 支持
- 可配置布局
- 逻辑与模板解耦
- 支持纯 XHTML5(无需额外标记)
- 触发事件
- 绘制表单(集合或映射到 HTML)
- 绝对化 URL
- 缓存
- 使用 PHP 函数、ZF2 视图变量、助手和过滤器
- 您仍然可以使用 phtml,但为什么!
为什么?
- 无逻辑标记的模板
- 启用缓存后非常快
- 覆盖配置设置以更改模块化项目的模板逻辑行为
设置
以下步骤是使此模块正常工作所必需的,考虑到 zf2-skeleton 或非常类似的应用程序
-
将
"minimum-stability": "dev"
添加到您的 composer.json 中,因为此模块正在开发中 -
运行
php composer.phar require webino/webino-draw:dev-develop
-
将
WebinoDraw
添加到启用的模块列表中
要求
- XHTML(5) 声明
快速入门
例如,将以下代码添加到您的模块配置中某个位置
'webino_draw' => [
'instructions' => [
// Add draw instructions here
'draw-node-example' => [
'locator' => 'body',
'value' => 'Hello Webino!',
],
],
],
...重新加载您的浏览器,您应该会看到“Hello Webino!”作为正文内容。
渲染基于映射到 DOM 节点的指令
'draw-node-example' => [ // custom name
'locator' => 'body', // node locator
'helper' => 'WebinoDrawElement', // draw helper
'value' => 'Hello Webino!', // helper options
],
您可以使用 CSS 选择器 或 XPath,甚至将它们组合起来将 DOM 节点映射到绘制指令。
'draw-node-example' => [
'locator' => [
'body a',
'.customclass',
'xpath=//title',
'xpath=//footer',
],
'value' => 'Hello Webino!',
],
注意:可以设置许多 CSS 或 / 和 XPath 定位器
使用 stackIndex 选项指定每个指令的优先级
'draw-node-example' => [
'stackIndex' => 9,
'locator' => 'body',
'value' => 'Hello Webino!',
],
在指令层次结构中,您可以使用相对定位器
'quick-contact' => [
'locator' => '.quick-contact', // the same node
'instructions' => [
'widget' => [
'locator' => '.', // the same node
'locator' => 'xpath=.', // the same node
// ...
],
],
],
注意:每个子定位器 CSS 选择器都将解析为相对的。如果您想通过绝对 CSS 选择器进行匹配,请以双斜杠开始,例如 //.quick-contact
使用 节点变量
'draw-node-example' => [
'locator' => 'a',
'value' => 'customprefix {$_nodeName} {$_nodeValue} {$_nodePath} customsuffix',
'html' => '<custom>{$_innerHtml}</custom>',
'replace' => '{$_outerHtml}<custom/>',
'attribs' => [
'title' => '{$_nodeValue} {$_href}',
'href' => '{$_href}#customfragment',
],
],
注意:节点变量以下划线为前缀,以避免冲突。
使用 视图变量
假设控制器操作返回具有多维数组的视图模型。
'draw-node-example' => [
'locator' => 'body',
'value' => '{$viewvar}',
],
设置和覆盖
'draw-node-example' => [
'locator' => 'body',
'value' => '{$viewvar}',
'var' => [
'set' => [
'viewvar' => 'customval',
],
],
],
获取变量
'draw-node-example' => [
'locator' => 'body',
'value' => '{$depthvar}',
'var' => [
'fetch' => [
'depthvar' => 'value.in.the.depth',
],
],
],
设置默认变量
'draw-node-example' => [
'locator' => 'body',
'value' => '{$viewvar}',
'var' => [
'default' => [
'viewvar' => 'defaultval',
],
],
],
推送变量
'draw-node-example' => [
'locator' => 'body',
'var' => [
'push' => [
'myvalue.in.the.depth' => 'mydepthvar',
],
],
],
使用 函数、视图助手 和 过滤器
'draw-node-example' => [
'locator' => 'body',
'value' => '{$customvar}',
'var' => [
'helper' => [
'customvar' => [
'customhelper' => [
'__invoke' => [[]],
],
'customfunction' => [[]],
],
],
'filter' => [
'pre' => [
'customvar' => [
'customfilter' => [],
'customfunction' => [],
],
],
'post' => [],
],
],
],
注意:在函数/方法参数中修改变量值、助手/过滤器定义接受 {$var}
通过视图数组循环
'draw-node-example' => [
'locator' => 'ul li',
'value' => '{$_key} {$_index} {$property}',
'loop' => [
'base' => 'array.in.the.depth',
'index' => '0',
'onEmpty' => [
'locator' => 'ul',
'replace' => '<p>You have no items.</p>',
],
],
],
注意:额外变量以前缀下划线开头,以避免冲突。
触发 事件
'event-example' => [
'locator' => 'body',
'trigger' => [
'event-example.test',
],
],
然后附加监听器
$this->getEventManager()->getSharedManager()->attach(
'WebinoDraw',
'event-example.test',
function(DrawEvent $event) {
// set custom variables
$event->getHelper()->setVars([]);
// do something with the nodes
$event->getNodes()->setValue("my node value");
// change instruction node
$event->setSpec([
// draw instructions
'value' => '{$_nodeValue} VALUE',
'attribs' => [
'title' => 'Hello from Controller!',
],
]);
}
);
从控制器设置指令
$this->getServiceLocator()->get('WebinoDraw')->setInstructions([
'custom' => [
'locator' => '.customclass',
'value' => 'Custom value',
],
]);
设置指令始终合并,因此在某些情况下,清除它们很有用
$this->getServiceLocator()->get('WebinoDraw')->clearInstructions();
缓存
'cache-example' => [
'locator' => 'body',
'cache' => 'exampleCacheTag',
'cache_key' => ['{$var}'],
'cache_key_trigger' => [
'draw.cache.byPage',
],
],
附加缓存键监听器
$this->getEventManager()->getSharedManager()->attach(
'WebinoDraw',
'draw.cache.byPage',
function(Event $event) use ($navigation) {
$page = $navigation->getActivePage();
return $page->getHref();
}
);
清除缓存
$this->getServiceLocator()->get('WebinoDrawCache')->clearByTags(['exampleCacheTag']);
注意:当加载缓存数据时,将跳过 draw 助手操作,也不会触发 AjaxEvent。
指令集
指令集允许您在自定义名称下配置一组绘制指令
'webino_draw' => [
'instructionset' => [
'customname' => [
// Add draw instructions here
],
],
],
稍后您可以获取这些指令并将它们设置到 WebinoDraw 服务中
$draw = $this->getServiceLocator()->get('WebinoDraw');
$draw->setInstructions(
$draw->instructionsFromSet('customname')
);
Ajax
WebinoDraw 支持Ajax,这意味着您可以从 Web 服务器请求布局体的任何片段,并通过网页 DOM 中的 JavaScript 更新元素。
假设Ajax是在网页背景中发送/接收数据的进程。为此使用JSON格式。
-
设置Ajax处理程序。使用以下jQuery脚本
jQuery(document).ready(function($){ $(document).on("click", ".ajax-link", function(event) { event.preventDefault(); $.get($(this).attr("href"), function(data) { // replace element HTML with each received fragment $.each(data.fragment, function(selector, html) { $(selector).replaceWith(html); }); // custom data whatever if (data.extraExample) { $(".my-ajax-data").html(data.extraExample); } }, "json"); }); });
注意:上述脚本使所有具有类名"ajax-link"的元素都具有Ajax功能。该元素必须有"href"属性。
注意:JSON
data.fragment
包含选择器 => XHTML
对。注意:我们可以接收自定义参数并对它们做任何事情。
-
将id和类名"ajax-fragment"添加到您想通过Ajax更改的每个元素上。
假设以下元素在布局的body标签中的某个地方
<div id="my-ajax-area" class="ajax-fragment">Ajax-able content</div>
-
现在,当您点击Ajax功能元素时,每个Ajax功能片段都将更新。
Ajax事件
Ajax请求触发Ajax事件,然后您可以添加自定义JSON数据并更改要渲染的片段的XPath。
$this->getEventManager()->getSharedManager()->attach(
'WebinoDraw',
AjaxEvent::EVENT_AJAX,
function(AjaxEvent $event) {
// add custom JSON data
$event->setJson(['extraExample' => 'my extra ajax']);
// change XPath of fragments to render
$event->setFragmentXpath('//*[contains(@class, "my-ajax-fragment"])');
}
);
注意:如果您使用JsonModel作为MvcEvent响应,则不会触发Ajax事件。
Ajax设置
有默认设置来配置Ajax支持
'webino_draw' => [
// container is the area to render (in the layout)
'ajax_container_xpath' => '//body',
// fragment is the part of the container to receive
'ajax_fragment_xpath' => '//*[contains(@class, "ajax-fragment") and @id]',
],
注意:只有与容器XPath匹配的元素才会渲染。
如果您想针对布局更具体地设置这些设置,可以覆盖它们。
布局可能包含许多Ajax容器和许多片段。您可以根据Ajax设置通过XPath匹配它们。例如,您可能只想渲染导航和内容,例如 'ajax_container_xpath' => '//nav|//content'
,然后也将它们作为片段接收 'ajax_fragment_xpath' => '//nav|//content'
。因此,只会渲染和接收所需的部件,从而通过跳过布局体中Ajax容器周围的头、尾和其他无用部分来节省资源。
辅助工具
通过消耗DOM节点、选项和数据来执行DOM节点操作,提供自定义类的模块化。
WebinoDrawElement
使用它来修改网页元素。许多选项,非常强大。
'draw-element-example' => [
'locator' => '.customclass',
'helper' => 'WebinoDrawElement', // default (not required to set)
// Helper options:
'value' => 'Draw element example value', // set node value
'render' => [
'script' => 'script/path' // render view script to variable
],
'fragments' => [ // HTML fragments of the template to variables
'frag' => '.frag-class' // pairs of customName => locator, gives us fragOuterHtml and fragInnerHtml variables
],
'html' => '<span>HTML value</span>{$script}', // set node XHTML
'attribs' => [ // set attributes
'title' => 'Attribute example'
],
'remove' => '.', // locator|array, removes target node
'replace' => '<strong/>', // XHTML, replaces node
'onEmpty' => [ // custom options if node is empty
'value' => 'Empty node example', // use same options as normal
],
'var' => [
'set' => [ // set variables values
'myvar' => 'myval', // key => value pairs
],
'fetch' => [ // fetch variables from multidimensional array
'myvar' => 'base.path', // local variable name => variable base path pairs
],
'default' => [ // set default variables values
'myvar' => 'mydefaultval', // key => default value pairs
],
'push' => [ // push variables values to the global context
'my.base.path' => 'myval', // custom variable base path => value pairs
],
'helper' => [ // use helpers on variables
'customvar' => [
'_join_result' => false, // bool, disable the string result joining, default true
'customhelper' => [ // zend helper
'__invoke' => [[]], // zend helper methods with params
],
'customfunction' => [[]], // use php function with params
],
],
'filter' => [ // filter variables
'pre' => [ // filter called before helpers
'customvar' => [
'customfilter' => [], // use zend filter with params
'customfunction' => [], // use php function with params
],
],
'post' => [
// filter called after helper, same as for pre
],
],
],
'onVar' => [ // variables logic
'customIndex' => [ // options per variable
'var' => '{$customvar}', // test variable value
'equalTo' => '', // condition method (or)
'notEqualTo' => '', // condition method
'instructionset' => [ // sub-instructionset to expand instructions
],
'instructions' => [ // sub-instructions processed when condition is true
],
],
],
'instructionset' => [ // instructionset to expand instructions
],
'instructions' => [ // sub-instructions to draw over nodes
// add different helper instructions
],
'trigger' => [
'event-example.test', // event name per item, identificator = WebinoDraw
],
'loop' => [ // loop node by view array items
'base' => 'depth.items', // path to view array
'index' => '0', // index start point (optional)
'offset' => '0', // items offset (optional)
'length' => '0', // items length (optional)
'shuffle' => false, // shuffle items
'helper' => function( // LoopHelper|callable, called on each item (optional)
$loopArgument, array $options
){},
'onEmpty' => [ // custom options if items array is empty
// use same options as normal
],
'instructionset' => [ // instructionset to expand instructions
],
'instructions' => [ // instructions to draw looped element nodes
// add same instructions as normal
],
],
'cache' => '', // string|array cache tags
],
WebinoDrawForm
使用它来渲染表单。如果 <form/>
模板为空,则使用默认渲染,否则尝试通过名称属性匹配表单元素。
'draw-form-example' => [
'localtor' => 'form.form-example',
'helper' => 'WebinoDrawForm',
// Helper options:
'form' => 'exampleForm', // form available via ServiceManager
'route' => 'example_route', // available route
'populate' => '{$values}', // populate form values
'text_domain' => __NAMESPACE__, // form translator text domain
'instructionset' => [ // instructionset to expand instructions
],
'instructions' => [ // sub-instructions to decorate the form
// add different helper instructions
],
'trigger' => [ // trigger event passes form to the event parameters
'form-example.event', // event name per item, identificator = WebinoDraw
],
'cache' => '', // string|array cache tags
],
假设表单模板
<form class="form-example">
<input name="example_text_element"/> <!-- form elements are mapped by name attribute -->
<input name="send"/>
</form>
如果您没有表单,可以轻松创建一个
'forms' => [
'exampleForm' => [
'hydrator' => \Zend\Stdlib\Hydrator\ArraySerializable::class,
'attributes' => [
'method' => 'post',
'class' => 'example-form',
],
'elements' => [
'example_text_element' => [
'spec' => [
'name' => 'example_text_element',
'options' => [
'label' => 'Label example',
],
'attributes' => [
'type' => 'text',
'placeholder' => 'Type something ...',
],
],
],
],
'input_filter' => [
'example_text_element' => [
'name' => 'example_text_element',
'required' => true,
'validators' => [
],
],
],
],
],
WebinoDrawAbsolutize
绝对化相对URL(默认属性:src、href、action)。
'absolutize' => [
'stackIndex' => 9999998,
'helper' => 'WebinoDrawAbsolutize',
'locator' => (new \WebinoDraw\Draw\Helper\Absolutize\AbsolutizeLocator)->getLocator(),
],
通过 my-attr 属性扩展定位器
'absolutize' => [
'locator' => [
'my-attr' => 'xpath=//@my-attr' . (new \WebinoDraw\Draw\Helper\Absolutize\AbsolutizeLocator)->getCondition(),
],
],
注意:现在您不需要在URL前加 $this->view->basePath()
。
陷阱
-
在出现问题时,使用
<![CDATA[ ]]>
与实体,如&
:<![CDATA[&]]>
-
您可能会遇到垃圾(编码)文本的结果,将布局中的meta charset替换为以下内容
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
-
要绘制表单集合,使用WebinoDraw FormElement和FormRow视图辅助工具。它解决了当使用Zend FormElement视图辅助工具时与翻译器的一些问题,因为它不允许将翻译器文本域传递给其元素。
-
要指定渲染表单元素的视图辅助工具,设置其
view_helper
选项。 -
如果您不想绝对化元素属性,请将其添加到其属性中的
data-webino-draw-absolutize="no"
。 -
当使用具有视图辅助工具的辅助工具时,如果多个方法在同一变量上调用,则自动连接字符串结果。使用
_join_result = false
选项禁用此行为。
示例
更多示例请参阅:examples/config/module.config.php
手动设置
-
安装ZendSkeletonApplication
-
设置WebinoDraw模块
-
设置模块测试配置
- 复制:
vendor/webino/webino-draw/test/resources/application.config.php
- 粘贴到应用程序:
config/application.config.php
(替换)
- 复制:
-
检查您的应用程序欢迎页面是否有变化
待办事项
- DrawHelper如何
- 添加DrawResized以调整图像大小
- 编写针对draw表单和新的功能(事件 + 子指令 + Ajax + 缓存)的测试
- 编写针对DrawPagination的测试 + 手册
- 编写 DrawTranslate 的测试和手册
- 编写 DrawElement {$_outerHtml} 的测试和示例
- 编写 DrawAjaxHtmlStrategy 的测试
- 编写关于变量 fetch _first 和 _last 魔术键的文档
- 编写对 onVar 支持的测试
- 编写扩展指令集的规格指令测试
- 禁用变量辅助工具的多方法调用,自动合并结果,向下不兼容
- 重新设计变量辅助工具和过滤器 API,因为辅助工具/过滤器名称作为键在通过配置合并时会导致问题,向下不兼容
- 编写循环辅助工具的手册和测试
- 升级 Zend MVC
- 升级 Zend Form
附录
请,如果您对这个 Zend 框架模块感兴趣,请报告任何问题,并不要犹豫贡献。我们非常欢迎对模块开发的任何贡献。