ecomfe / moye

A Simple UI Library for ZX
73 stars 32 forks source link

Smarty预渲染功能 #50

Closed jinzhubaofu closed 9 years ago

jinzhubaofu commented 9 years ago

为什么需要预渲染模板?

moye广泛使用在中间页和卡片系统中,这两类页面对于性能要求非常高。在这种情况下,需要在尽可能早的时间点上提供用户正确和稳定的视觉展现。而使用js脚本来完成首屏元素的生成/渲染是不可取的。

因此,我们希望在组件的DOM是直接由smarty模板渲染完成的。我们通过实现一系列smarty函数来提供一种快捷实用的构建首屏控件dom。这样做有几个好处:

  1. 性能更好
  2. moye控件在页面中经常被重复使用多次,依照Don’t Repeat Yourself原则,我们应当把这些代码抽象出来,以减少重复代码,降低维护成本。
  3. 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%}
  }
}

最后,通过下边这条语句就可以得到Buttondom结构了:

{%call Button data=$ui.btn%}

渲染的结果:

<button type="button" class="ui-button" data-ui-id="btn">test</button>

如何开发控件的smarty预渲染函数

原则上,我们只生成首屏可视元素,以及必要的属性。首屏不可见的元素(如浮层)可以交由javascript来完成渲染

我们提供了一个base.tpl的基础函数库,提供了一些基础的方法,例如:

  1. getPartClassName()等同于control.helper.getPartClassName()
  2. 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插件的方式来实现上述的功能。感兴趣的同学可以调研一下。

jinzhubaofu commented 9 years ago

时间安排:

  1. 方案讨论 03/09 - 03/12
  2. 开发阶段 03/13 - 03/22

周四我会提供一个smarty预渲染模板的开发环境。

jinzhubaofu commented 9 years ago

我刚刚提交了预渲染相关的一些代码,稍作说明。

如何使用demo进行开发

  1. 首先,要求大家首先安装php-cgiphp-cgi的安装请自行google。在开发前请保证在terminal中输入php-cgi -v可以看到下面的结果(php版本只要高于5.3即可):

    image

  2. 由于smarty代码库没有纳入git管理,因此在使用demo进行开发前需要手动安装它。从smarty的官网下载到源码后,将源码放置在example/smarty/lib目录中。

    image

  3. 启动edp webserver。我们通过edp-webserverphp-cgi处理器来调用php-cgi,现在已经配置好了。现在在浏览器里输入localhost:8848/example/smarty/index.php即可看到效果:

    image

代码位置与结构

  1. 请将预渲染模板的源代码放置在src/tpl/smarty目录下
  2. 请将example/smarty/index.tpl这个模板中,添加demo相关的代码。
  3. 请在exmaple/smarty/index.less中引入控件样式

    image

  4. 添加控件的配置数据。

    请注意这个文件必须是保持严格的json格式,否则smarty没有办法正确地读取其中的数据。

  5. 我们在src/tpl/smarty/base.tpl中提供了以下几个通用函数,大家可以在自己的控件模板中使用:
    1. getPartClassName() 等同于control.helper.getPartClassName()
    2. getStateClassName() 等同于control.helper.getStateClassName()
    3. getClassName() 等同于上边两个函数
    4. getPartId() 等同于control.helper.getPartId()
    5. dataClick() 生成data-click属性,为moye/log提供点击日志数据

以上,如果遇到任务问题,可以联系我。