模板引擎


模板引擎是基于预定义好的模板,使用填充数据(XCO对象)进行数据填充,得到渲染后的HTML代码。

XCO模板引擎的优势:

  1. HTML代码和JS代码分离
  2. 保持原有的HTML代码和结构
  3. 进一步提高编码效率

1. 使用示例

定义模板:

<div id="container"><!--
    <p>用户ID: #{id}</p>
    <p>用户名: #{name}</p>
--></div>

填充数据

<script type="text/javascript" src="/js/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="/js/xco-1.0.1.js"></script>
<script type="text/javascript" src="/js/xco.jquery-1.0.2.js"></script>
<script type="text/javascript" src="/js/xco.variable-1.0.1.js"></script>
<script type="text/javascript" src="/js/xco.template-1.0.1.js"></script>
<script type="text/javascript">
    XCOTemplate.pretreatment('container');               // 模板预处理

    function doSubmit() {
       var xco = new XCO();
       // 设置请求参数的值
       var options = {
         url : "/m1.xco",
         data : xco,
         success : doCallBack
       };
       $.doXcoRequest(options);
    }
    function doCallBack(data) {
       var html = XCOTemplate.execute("container", data);       // 填充模板, data为XCO对象
       document.getElementById("container").innerHTML = html;    // 渲染页面
    }
</script>

*说明:*doCallBack方法中的data参数为XCO请求后的返回结果,是一个XCO对象,用XML格式表示如下:

<?xml version="1.0" encoding="UTF-8"?>
<X>
    <I K="id" V="1001"/>
    <S K="name" V="张三"/>
</X>

渲染后的HTML

<div id="container">
    <p>用户ID: 1001</p>
    <p>用户名: 张三</p>
</div>  

类库说明

  1. xco.variable-1.0.1.js 标记解析类库
  2. xco.template-1.0.1.js 模板引擎类库

2.模板的定义和使用

如何定义一个模板呢?之前的示例已经给出答案,我们是通过HTML中的注释标签<!--...-->来定义模板。注意:一个模板一定要有一个所属的容器,否则我们怎么找到他呢。在模板中,我们可以设置一些标记,随后我们在模板填充的时候,将这些标记替换成我们希望的内容。

模板中标记分为两种,一种是变量替换标记,一种是函数替换标记。

2.1 变量替换

变量替换指的将标记中的变量所对应的内容替换此标记。变量替换的标记格式为#{xxx},其中#表示该标记为变量替换标记,xxx为变量名。

2.1.1 变量替换之默认值

#{xxx|yyy}表示带有默认值的变量替换标记。其中:xxx为变量名,|表示后续的yyy为默认值。 当填充数据中,变量xxx所对应的值不存在的时候,将使用此默认值进行替换。

示例

<div id="container"><!--
    <p>#{x|123}</p>
    <p>#{y|'中国'}</p>
--></div>

填充的数据

<?xml version="1.0" encoding="UTF-8"?>
<X>
    <I K="x" V="1001"/>
</X>

渲染后的HTML

<div id="container">
    <p>1001</p>
    <p>中国</p>
</div>

说明:

如果模板填充数据中存在x,则取x的值进行替换,否则此处使用默认值123进行替换;如果模板填充数据中存在y,则取y的值进行替换,否则此处使用默认值中国进行替换;

2.1.2 变量替换之表达式

在变量替换标记中,允许存在运算表达式;模板引擎会将表达式运算结果作为替换内容。

示例

<div id="container"><!-- 
    <p>#{x+y}</p>
    <p>#{x*y}</p>
    <p>#{x+y*z}</p>
    <p>#{money + '$'}</p>
 --></div>

填充的数据

<?xml version="1.0" encoding="UTF-8"?>
<X>
    <I K="x" V="1"/>
    <I K="y" V="2"/>
    <I K="z" V="3"/>
    <D K="money" V="1558.3"/>
</X>

渲染后的HTML

<div id="container">
    <p>3</p>
    <p>2</p>
    <p>7</p>
    <p>1558.3$</p>
</div>

说明:

目前支持的运算符包括:+-*/()。如果变量替换标记中的变量均为Number类型,则表达式为四则运算表达式,运算后的结果为Number类型;如果其中变量为String类型,则表达式代表字符串相加,运算后的结果为String类型。

2.1.3 变量替换之函数调用

#{xxx@yyy}表示带有函数调用的变量替换标记。其中:xxx为变量名,@表示后续的yyy为所调用的函数。 模板引擎会对于带有函数调用的变量替换标记的处理流程是:

  1. 取得变量xxx所对应的值,假设为R1
  2. R1作为yyy入参,执行yyy函数,返回结果假设为R2
  3. R2作为替换内容进行替换;

示例

<div id="container"><!-- 
    <p>#{create_time@formatDateTime}</p>
 --></div>

填充数据

<?xml version="1.0" encoding="UTF-8"?>
<X>
    <A K="create_time" V="2016-08-03 19:27:06"/>
</X>

相关函数

function formatDateTime(_date) {
    return this.format(date, "yyyy-MM-dd");       // 格式化时间
}

渲染后的HTML

<div id="container">
    <p>2016-08-03</p>
</div>

说明

对于函数调用这种方式,一般的应用场景是对于返回结果中的值做二次处理。比如之前示例中的create_time需要格式化后再进行替换。

2.2 函数替换

函数替换指的是直接将一个函数的返回值作为替换内容。函数替换的标记格式为@{xxx},其中@表示该标记为函数替换标记,xxx为函数名。

示例

<div id="container"><!-- 
    <p>@{getOrderOp}</p>
 --></div>

填充数据

<?xml version="1.0" encoding="UTF-8"?>
<X>
    <L K="order_id" V="10001"/>
    <I K="order_state" V="1"/>
</X>

调用示例

function doCallBack(data) {
    var ext = {                                  // 函数容器对象
       getOrderOp : function(xco) {                 // 对应函数替换标记中的函数
         if(1 == xco.get('order_state')){
          return '<a href="###" onclick="pay(' + xco.get('order_id') + ')">支付</a>';
         } else if(2 == xco.get('order_state')){
          return '<a href="###" onclick="confirmReceipt(' + xco.get('order_id') + ')">确认收货</a>';
         } else {
          return '<a href="/order_detail.jsp?order_id=' + xco.get('order_id') + '">查看详情</a>';
         }
       }
    }
    var html = XCOTemplate.execute("container", data, ext);       // 填充模板, data为XCO对象
    document.getElementById("container").innerHTML = html;     // 渲染页面
}

渲染后的HTML

<div id="container">
    <p><a href="###" onclick="pay(10001)">支付</a></p>
</div>

说明

在使用函数替换的时候,需要额外传入一个ext对象,该对象中所包含的函数(方法)即为函数替换所用到的函数。对于函数getOrderOp的入参xco,就是填充模板时传入的填充数据data,由框架自动传入。

函数替换和变量替换之函数调用的区别

  1. 入参不同;函数替换的入参为整个填充数据对象,变量替换之函数调用的入参为填充数据中某一个值;
  2. 变量替换之函数调用一般用作于数据的二次处理,而函数替换一般用作为较为复杂的HTML代码构建;

2.3 列表渲染

对于使用模板进行页面渲染,最常见的场景就是列表渲染。

定义模板:

<table>
    <thead>
       <tr>
         <th>用户ID</th>
         <th>用户姓名</th>
       </tr>
       <tbody id="users"><!-- 
         <tr>
          <td>#{users[i].user_id}</td>
          <td>#{users[i].user_name}</td>
         </tr>
        --></tbody>  
    </thead>
</table>

填充的数据

<?xml version="1.0" encoding="UTF-8"?>
<X>
    <XL K="users">
       <X>
         <L K="user_id" V="101"/>
         <S K="user_name" V="张三"/>
       </X>
       <X>
         <L K="user_id" V="102"/>
         <S K="user_name" V="李四"/>
       </X>
       <X>
         <L K="user_id" V="103"/>
         <S K="user_name" V="王五"/>
       </X>
       <X>
         <L K="user_id" V="104"/>
         <S K="user_name" V="赵六"/>
       </X>
    </XL>
    <I K="$$CODE" V="0"/>
</X>

调用示例

function doCallBack(data) {
    var dataList = data.getXCOListValue("users");
    var html = '';
    for (var i = 0; i < dataList.length; i++) {
        data.setIntegerValue("i", i);
        html += XCOTemplate.execute("users", data);
    }
    document.getElementById("users").innerHTML = html;   
}

渲染后的HTML

<table>
    <thead>
       <tr>
         <th>用户ID</th>
         <th>用户姓名</th>
       </tr>
       <tbody id="users">
         <tr>
          <td>101</td>
          <td>张三</td>
         </tr>
         <tr>
          <td>102</td>
          <td>李四</td>
         </tr>
         <tr>
          <td>103</td>
          <td>王五</td>
         </tr>
         <tr>
          <td>104</td>
          <td>赵六</td>
         </tr>
       </tbody>       
    </thead>
</table>