为什么需要预渲染模板?
moye
广泛使用在中间页和卡片系统中,这两类页面对于性能要求非常高。在这种情况下,需要在尽可能早的时间点上提供用户正确和稳定的视觉展现。而使用js
脚本来完成首屏元素的生成/渲染是不可取的。
因此,我们希望在组件的DOM是直接由smarty
模板渲染完成的。我们通过实现一系列smarty
函数来提供一种快捷实用的构建首屏控件dom
。这样做有几个好处:
- 性能更好
moye
控件在页面中经常被重复使用多次,依照Don’t Repeat Yourself
原则,我们应当把这些代码抽象出来,以减少重复代码,降低维护成本。
moye
控件内部结构复杂,手动编写其dom
结构对于使用者而言是非常痛苦的。难以记忆的同时,使用者对于控件的内部dom
结构的过度关注也违背了开闭原则
。对于一个控件来讲,应当支持对它的扩展,而不是去修改它。
如何使用预渲染模板
首先,需要在smarty
模板中引入我们提供的函数库,例如
{%include file="path/to/moye/tpl/Button.tpl"%}
其次,生成一个控件配置参数。例如从某个配置文件中读取:
// ui.json.tpl
{
"btn": {
"id": "btn",
"type": "Button",
"text": "test"
}
}
// index.tpl
{%include file="path/to/moye/tpl/Button"%}
{%include file="./ui.json.tpl" assign="ui"%}
{%$ui = $ui|json_decode:true%}
由于我们的参数配置文件也是一个smarty
模板,所以我们可以在这个文件中尽情使用smarty
的各项功能。
例如:
{
"btn": {
"id": "btn",
"type": "Button",
"text": {%if $a > 100%}"test"{%else%}hello, world{%/if%}
}
}
最后,通过下边这条语句就可以得到Button
的dom
结构了:
{%call Button data=$ui.btn%}
渲染的结果:
<button type="button" class="ui-button" data-ui-id="btn">test</button>
如何开发控件的smarty预渲染函数
原则上,我们只生成首屏可视元素,以及必要的属性。首屏不可见的元素(如浮层)可以交由javascript
来完成渲染
我们提供了一个base.tpl
的基础函数库,提供了一些基础的方法,例如:
getPartClassName()
等同于control.helper.getPartClassName()
getStateClassName()
等同于control.helper.getStateClassName()
小伙伴可以使用这两个函数来辅助构建自己的控件模板。
示例:Button
模板函数
{%function name=Button%}{%strip%}
<button type="{%if isset($data.mode)%}{%$data.mode|escape:html%}{%else%}button{%/if%}"
class="{%getPartClassName data=$data%}"
{%if isset($data.id)%}data-ui-id="{%$data.id%}"{%/if%}
{%if isset($data.disabled) and $data.disabled%}disabled="disabled"{%/if%}>
{%$data.text|escape:none%}
</button>
{%/strip%}{%/function%}
PS: 目前我们采用的提供模板函数的方式来实现。在编写过程中,操作数据是比较复杂的。同时,如果想要实现与javascript
同等复杂逻辑的dom
结构,也是比较痛苦的事情 。所幸,强大的smarty
也提供了插件机制,我们也可以通过编写smarty
插件的方式来实现上述的功能。感兴趣的同学可以调研一下。