jstemplate 入门与实践

      在web前端开发,特别是富ajax应用,经常会出现前端大段大段拼接html的片段,这使得本事很简单的渲染逻辑变得很难维护也很难阅读。为了解决这一问题,借鉴目前比较流行的模版语言的思想,jstemplate作为这方面比较流行的解决方案值得学习。自己在学习的过程中,将官方的文档做一简单整理,翻译给大家。

 

一.helloworld(完整例子

     1)模版文件

 

 <div id="t1">
    <h1 jscontent="title"></h1>
    <ul>
      <li jscontent="$this" jsselect="favs"></li>
    </ul>
  </div>

 

    2)填充数据

 

  var favdata = {
    title: 'Favorite Things', 
    favs: ['raindrops', 'whiskers', 'mittens']
  };

 

    3)添加js库

 

<script src="util.js" type="text/javascript"></script>
<script src="jsevalcontext.js" type="text/javascript"></script>
<script src="jstemplate.js" type="text/javascript"></script>
 

    4)调用

 

function showData(data) {
      // This is the javascript code that processes the template:
      var input = new JsEvalContext(data);  //初始化数据
      var output = document.getElementById('t1'); //输出模版
      jstProcess(input, output);
    }

 

    当showdata调用后,模版渲染完毕产生的html即:

 

 

<div jstcache="0" id="t1">
    <h1 jstcache="1" jscontent="title">Favorite Things</h1>
    <ul jstcache="0">
      <li jsinstance="0" jstcache="2" jsselect="favs"
          jscontent="$this">raindrops</li>
      <li jsinstance="1" jstcache="3" jsselect="favs"
          jscontent="$this">whiskers</li>
      <li jsinstance="2" jstcache="4" jsselect="favs"
          jscontent="$this">mittens</li>
    </ul>
  </div>

 

二.有用属性标签和概念解释

 

     上面已经对jstemplate做了一个简单的应用,然而要真的理解它,并使用其高级点应用,需要了解一下一些概念。

 

   1. 处理环境(processing  environment03-environ.html ]

 

        有几个变量需要注意:

 

  • JsEvalContext 像其他context一样,它在整个代码执行过程中存在,存放所有的上下文数据,可以是字符串也可以json数据,一切你感兴趣的和有用的数据。
 var mydata = {dataProperty: 'Nonny'};
  var context = new JsEvalContext(mydata);
  context.setVariable('declaredVar', 'Ho');
  • this 和 $this
    this即为模版定义的html的某个节点,而$this是该节点绑定的context的数据。如
     

 

  <div id="witha">
  <div id="Hey" jscontent="this.parentNode.id + this.id + 
      dataProperty + $this.dataProperty + declaredVar"></div>
  </div>
 

 

     这里this即为Hey div。而$this为context。

 

  2.jscontent

 

 <div id="tpl">
    <span jsselect="username" jscontent="$this"></span>'s Address Book
  </div>
 

 

    即将该属性所在的节点值替换成jscontent的属性值。

 

  3.jsselect

 

    jsselect可以生成一个基于原context的新context。对于数组的数据,它能够自动遍历所有的元素并执行处理。

 

   语言有点抽象,举个例子:

 

  假如context值为:

 

 var tplData = {
    username:"Jane User",
    addresses:[
      {location:"111 8th Av.", label:"NYC front door"},
      {location:"76 9th Av.", label:"NYC back door"},
      {location:"Mountain View", label:"Mothership"}
    ]};
 

   模版为:

 

 <div id="tpl">
    <span jsselect="username" jscontent="$this"></span>'s Address Book
  </div>
 

   由于jsselect 的先于其他的属性执行(除transclude),所以新的该节点绑定的contex为字符串:Jane User,故渲染完成后为:

 

 

<span jscontent="username" jstcache="1">Jane Userff</span>

   这里可以看出,实际上和模版为:

 

    <span jscontent="username"></span>'s Address Book

   的一样。

 

  因此,此标签更多用在数组上。

 

 <table cellpadding="5">
  <tr><td><h2>Location:</h2></td><td><h2>Label:</h2></td></tr>
  <tr jsselect="addresses"><td jscontent="location"></td><td jscontent="label"></td></tr>
  </table>

  当处理器执行jsselect时,由于addresses是个数组,所以会遍历产生3个context,渲染的结果即:

 

<tr jsselect="addresses" jstcache="2" jsinstance="0">
<td jscontent="location" jstcache="3">111 8th Av.</td>
<td jscontent="label" jstcache="4">NYC front door</td>
</tr>
<tr jsselect="addresses" jstcache="2" jsinstance="1">
<td jscontent="location" jstcache="3">76 9th Av.</td>
<td jscontent="label" jstcache="4">NYC back door</td>
</tr>
<tr jsselect="addresses" jstcache="2" jsinstance="*2">
<td jscontent="location" jstcache="3">Mountain View</td>
<td jscontent="label" jstcache="4">Mothership</td>
</tr>

 4.jsdisplay 06-jsdisplay.html07-jsdisplay-empty.html ]

 

     此属性的值如果非0,true,非""时条件成立,将该节点的css属性display设置为none。对于设置块的动态隐藏有奇效。

 

  5.transclude 08-transclude.html ]

 

     对于嵌套的数据结构,对于模版来讲,嵌套深度并不能知晓,深度是由数据控制的,为了能够方便写出此类场景的模版,引入了该属性。例:

<html>
<head><title>Outline Tree Using Jstemplates</title>
  <script src="../util.js" type="text/javascript"></script>
  <script src="../jsevalcontext.js" type="text/javascript"></script>
  <script src="../jstemplate.js" type="text/javascript"></script>
  <script type="text/javascript">
    // Hierarchical data:
    var tplData = 
      { title: "Jstemplates", items: [
        { title: "Using Jstemplates", items: [
          { title: "The Jstemplates Module"},
          { title: "Javascript Data"},
          { title: "Template HTML"},
          { title: "Processing Templates with Javascript Statements"}
          ]
        },
        { title: "Template Processing Instructions", items: [
          { title: "Processing Environment" },
          { title: "Instruction Attributes", items: [
            {title: "jscontent"}, {title: "jsselect"}, {title: "jsdisplay"}, 
            {title: "transclude"},{title: "jsvalues"}, {title: "jsskip"}, {title: "jseval"}
          ]}
        ]}
      ]};
      
    var PEG_NAME = 'peg';
    var TEMPLATE_NAME = 'tpl';
    
    // Called by the body onload handler:
    function jsinit() {
      pegElement = domGetElementById(document, PEG_NAME);
      loadData(pegElement, TEMPLATE_NAME, tplData);
    }
  
    function loadData(peg, templateId, data) {
      // Get a copy of the template:
      var templateToProcess = jstGetTemplate(templateId);  //clone出一个,而非直接替换使用
      
      // Wrap our data in a context object:
      var processingContext = new JsEvalContext(data);
  
      // Process the template
      jstProcess(processingContext, templateToProcess);
      
      // Clear the element to which we'll attach the processed template:
      peg.innerHTML = '';
      
      // Attach the template:
            domAppendChild(peg, templateToProcess);
    }
    </script>
    <link rel="stylesheet" type="text/css" href="css/maps2.deb.css"/>
</head>
<body οnlοad="jsinit()">

<!-- 
This is the div to which the instantiated template will be attached.
-->
<div id="peg"></div>

<!--
A container to hide our template:
-->
<div style="display:none">
<!-- 
This is the template div. It will be copied and attached to the div above with:
 var apt = jstGetTemplate('apt');
 appendChild(panel, apt)
-->
  <div id="tpl">
    <span jscontent="title">Outline heading</span>
    <ul jsdisplay="items.length">
      <li jsselect="items">
        <!--Recursive tranclusion: -->
        <div transclude="tpl"></div>
      </li>
    </ul>
  </div>

</div>
</body>
</html>
 

 

 

  6.jsvalues(jsvars同)

 

  • $ 可以通过$引用  JsEvalContext,如果  jsvalues="$varname:varvalue",则可以通过 $varname来引用
  • . 可以修改该节点的属性。如 jsvalues=".id:'Joe';.style.fontSize:'30pt'",这该节点的id,style就会被赋值为该值
  • 表达式   jsvalues="sum:1+2" =  this.setAttribute('sum', '3').

 

    7.jseval 11-jseval.html ]

 

       该属性顾名思义,其值是一段js,在渲染所在节点时可以获得执行。例如:

利用$,创建一个counter变量

 

processingContext.setVariable('$counter', counter);

 

<span jscontent="title" 
          jseval="title? $counter.full++: $counter.empty++">
      Outline heading
    </span>

   在其他片段可以引用。

<div id="titleCountTpl">
  <p>
      This outline has <span jscontent="$counter.empty"></span> empty titles 
      and <span jscontent="$counter.full"></span> titles with content.
  </p>
  </div>

 

     8.jsskip

 

      意义同jsdisplay,当值为真时, 处理器将不在处理当前节点和子节点。 它在增加处理性能方面有一定作用,比如避免不必要的深层树遍历。

 

 

<div id="tpl2">
<h1 jsselect="username" jscontent="$this + '\'s Previous Searches'"></h1>
<ul jsskip="true">
<li jsselect="addresses" jscontent="location"></li>
</ul>
</div>
 

上面的属性的执行顺序为:

 

transclude. If a transclude attribute is present no further Jst attributes are processed. jsselect. If  jsselect is array-valued, remaining attributes will be copied to each new duplicate element created by the  jsselect and processed when the new elements are processed. jsdisplay jsvars jsvalues jseval jsskip jscontent

 

参考:http://code.google.com/intl/zh-CN/apis/jstemplate/docs/instructions-ref.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值