2010-02-14 52 views
5

我正在尝试开发一种在JavaScript中创建模板的简单方法。基本的想法是,我在代表JavaScript中对象的UI的页面中获得了HTML,并且该HTML中的变量被JavaScript对象的属性替代。把它看作是将JavaScript对象绑定到HTML演示文稿的技巧。改进一个简单的JavaScript模板技术

任何批评?我应该以某种方式使用文档片段吗?我基本上是在寻找一个代码审查这一个。我会很感激任何反馈。 (请注意,这应该是独立于框架的。)这是一个工作示例。

<html> 
<body> 

    <!-- where templates will be injected into --> 
    <div id="thumbContainer"></div> 

    <!-- template used for thumbnails --> 
    <div id="thumbTemplate" style="display:none"> 
     <div class="thumb"> 
      <div>${caption}</div> 
      <div>${image}</div> 
     </div> 
    </div> 

</body> 

<script type="text/javascript"> 
(function() { 

    // Cache the templates' markup in case that template is used again 

    var cache = []; 

    // Magic 

    document.templatized = function(templateId, properties) { 

     // Get the template from cache or get template and add to cache 

     var template = cache[templateId] || (function() { 
      cache[templateId] = document.getElementById(templateId).innerHTML; 
      return cache[templateId]; 
     })(); 

     // Create the DOM elements that represent the markup 

     var shell = document.createElement('div'); 

     shell.innerHTML = template.replace(/\$\{(\w+)\}/g, function(match, key){ 
      return properties[key] || match; 
     }); 

     // Return those DOM elements 

     return shell.children[0].cloneNode(true); 
    }; 
})(); 

// Create DOM elements with values bound to thumbnail object 

var thumb = document.templatized('thumbTemplate', { 
    caption: 'Summer', 
    image: (function() { 
      // More complicated logic that requires conditions here... 
     return '<img src="test.png" />'; 
    })() 
}); 

// Display on page by inserting into DOM 

document.getElementById('thumbContainer').appendChild(thumb); 
</script> 
+0

+1 for // magic – cherouvim 2010-02-14 06:27:44

+0

哈哈,谢谢! :) – JamesBrownIsDead 2010-02-14 06:28:55

回答

2

该代码是整洁的。

我想在html注释中使用模板,所以1)它不会被渲染(不需要显示:无需破解),2)我可以拥有不验证的东西,比如作为直接<tr>

另外我会删除硬编码'div'创建,所以我可以支持从任何html元素开始的模板片段。

稍后我会添加图导航(例如$ {foo.bar}),迭代和if语句。

2

+1 cherouvim:您将模板用作文本,因此请将其保留为文本。您可以将它作为注释传递给脚本,也可以将它作为JSON编码的字符串传递,但使用标记可能会带来危险。

例如:

<form method="${mymethod}"><table> 
    <tr><td> 
     <${mylisttype}> 
      <li> 
       <input name="foo" value="${myvalue}"> 
      </li> 
     </${mylisttype}> 
    </td></tr> 
    ${extrarow} 
</table></form> 

说明有些事情你不能可靠地由于“固定”的标记和改变返回innerHTML回到浏览器的模板语言做:在form可突变为method="get" (或者在IE中,忽略FSR);除非您处于XML模式,否则会添加一个<tbody>元素;可变元素根本不起作用; ${extrarow}文本直接在表内无效;当页面加载时,input.value可能会发生变化,因为浏览器试图重新设置表单字段值,IE错误地将字段值更改反映为属性/ innerHTML。

另外,我会强烈建议添加HTML编码特征(与&lt;替换&&amp;<并与类似的参考文献的任何属性值的分隔符)。使用模板语言的经验表明,想要在文档中插入文本字符串比一段标记更为常见。当你这样做:

Hello, ${name}! 

不应用逃逸到变量name,你打开你的应用到跨站点脚本攻击。现代模板语言通过默认应用HTML编码避免了这种情况,因为编码人员懒得手动执行(如果他们甚至理解所涉及的问题)。这就是为什么绝大多数PHP应用程序容易受到XSS攻击。

不要把同样的问题带给客户端;使其在默认情况下逃生,提供一个标志,说你不想逃避了要插入原始标记(通常是比较少的)情况:比HTML注释,你可以拥有它

<div>${caption}</div> 
<div>${image|markup}</div> 
+1

html编码功能将会很棒 – cherouvim 2010-02-14 10:02:55

1

相反把它的标签,例如:

<script type="text/html" id="mytemplate"> 
    ... template here ... 
</script> 

这里的美景是所有浏览器和所有正确写入机器人会忽略脚本块在那里不知道如何解释它们;你可以很容易地通过ID访问内容(就像它是一个div一样)。

+0

这就是几个jQuery模板插件以及微软的模板建议。 http://wiki.github.com/nje/jquery/jquery-templates-proposal – R0MANARMY 2010-04-29 04:11:53