DojoX DTL 是 DTL(Django Template Language)的 Dojo 实现版本。Neil Roberts 将 DTL 移植到 DojoX 中,并在 DTL 只支持文本基础上增加了对 HTML 元素的支持。DojoX DTL 完全实现了对 DTL 语法的支持,已有的 Django 模板可以很容易地移植到 DojoX DTL。
Django是一款基于 Python 语言的开源 Web 开发框架,主要目的是支持快速的基于数据库的 Web 开发,使用 Django,花极少时间即可构建和维护高质量的 Web 应用。
DTL 是 Django 框架的模板系统语言。DTL 语法简单,提供了很好的扩展性,可以很容易地实现自定义标签(Tag)和过滤器(Filter),是 Django MVC 中的重要组成部分。使用模板的一个主要好处是将页面展示和业务处理逻辑分开,模块之间松散耦合,Web 界面设计人员和业务逻辑开发人员可以独立工作而不互相影响。
一个 Django 模板是将文档的数据和展示分离的一段文本。模板定义了占位符和若干基本的控制逻辑,即标签。标签控制了文档如何显示。通常来说 Django 模板用来输出 HTML 文本,但是 Django 模板也可以用来产生任何基于文本的格式。
下面是一个公司感谢客户下订单的例子,模板如下:
清单 1. DTL 示例
<html>
<head><title>Ordering notice</title></head>
<body>
<p>Dear {{ person_name }},</p>
<p>Thanks for placing an order from {{ company }}. It's scheduled to
ship on {{ ship_date|date:"F j, Y" }}.</p>
<p>Here are the items you've ordered:</p>
<ul>
{% for item in item_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% if ordered_warranty %}
<p>Your warranty information will be included in the packaging.</p>
{% endif %}
<p>Sincerely,<br />{{ company }}</p>
</body>
</html>
|
这个模板包含了基本的 HTML 元素,一些变量和模板标签,让我们逐个分析:
- 变量:在“{{”和“}}”之间的文本,如 {{ person_name }} 表示在当前位置输出变量 person_name 的值。
- 块标签(block tag):在“{%”和“%}”之间的文本,如 {% if ordered_warranty %}。块标签的定义很宽泛,只是告诉模板系统去执行一些操作,而具体做什么则由标签来决定。上面的例子定义了两个块标签,{% for item in item_list %} 和 {% if ordered_warranty %},分别使用了 for 标签和 if 标签。for 标签定义了一个简单的循环,对指定序列进行迭代。if 标签则是一个条件判断,如果 ordered_warranty 为真,则显示 {% if ordered_warranty %} 和 {% endif %} 之间的所有内容,如果为假则不显示。if 标签也支持 {% else %} 和其它的逻辑表达式。Django 模板系统定义了很多内建的标签,具体参见 其文档。开发人员也可以创建自定义的标签来扩展 Django 模板系统的功能。
- 过滤器(filter):过滤器用来改变变量的显示方式。如 {{ ship_date|date:"F j, Y" }} 表示对变量 ship_date 使用过滤器 date 后输出。"F j, Y"是过滤器 date 的参数,指定了输出的格式。过滤器使用“|”符号,即 Unix 的管道符号。Django 模板系统也定义了很多内建的过滤器,具体参见 其文档。当然开发人员也可以创建自定义的过滤器。
DojoX DTL 包括文本和 HTML 两个实现,构造函数分别为 dojox.dtl.Template 和 dojox.dtl.HtmlTemplate。这两个构造函数都可以接受一个字符串或 URL 作为参数,HTMLTemplate 也可以传入一个 DOM 节点作为参数。
Template 只适用于文本,不能用它来操纵 DOM 节点。但是我们可以用它来产生文本,然后将生成的文本作为某个 DOM 节点的 innerHTML。
HTMLTemplate 是 Template 的扩展,这就是说 HTMLTemplate 不仅支持所有的 Template 操作,还支持直接对 DOM 节点的操作。例如一个节点位于 {% if %} 块标签中,如果 if 标签求值为真,那么这个节点会被添加到 DOM 中,如果 if 标签求值为假,则这个节点将会从 DOM 中移除。
DojoX DTL 的使用与 Django Template Language 类似,首先创建一个 Template 对象,然后创建模板的上下文信息(context,可以理解为变量的集合),最后将 context 作为参数调用 Template 对象的 render 方法输出结果。
清单 2. Hello World
dojo.require("dojox.dtl");
dojo.require("dojox.dtl.Context");
var template = new dojox.dtl.Template("Hello {{ place }}!");
var context = new dojox.dtl.Context({
place: "World"
});
alert(template.render(context));
|
上面的例子首先调用 dojox.dtl.Template 构造函数创建了一个编译好的模板对象 template,该模板定义了对一个变量 place 的引用。这个模板对象可以在以后随时被调用,而不用每次都重新编译。然后调用 dojox.dtl.Context 创建了上下文对象 context,定义了 place 变量。这时调用 template.render(context) 会输出“Hello World”。
前面提到 Template 只适用于文本,但是产生的文本可以作为 DOM 节点的 innerHTML。为了方便这种类型的应用,Template 对象还有一个 update 方法,用来将模板输出的文本作为一个或多个节点的 innerHTML。update 方法有两个参数,第一个是要更新的节点引用、节点 ID 或是通过 dojo.query 返回的节点列表,第二个参数类型是对象或是 URL,作为模板的上下文信息。
我们知道 dojo.query 返回一个 NodeList 对象,通过这个对象可以很方便地操作查询返回的结果集合。通过引入 dojox.dtl.ext-dojo.NodeList,我们可以将模板应用于 dojo.query 返回的结果集合。如下面的例子:
清单 3. dojo.query 中的模板使用
dojo.require("dojox.dtl.ext-dojo.NodeList");
dojo.query(".fruit").dtl("Fruit is: {{ fruit }}", { fruit: "apple" });
|
我们可以调用 NodeList 对象的 dtl 方法,将第一个参数作为模板,第二个参数作为上下文信息,然后把模板的输出结果作为 NodeList 中每个结果对象的 innerHTML。dtl 方法的参数同 Template 对象的 update 方法。
在创建自定义 widget 的时候,我们一般会将 dijit._Widget 和 dijit._Templated 作为父类。而通过 DojoX DTL 我们也能实现自定义 widget,如下面的例子:
清单 4. widget 示例
dojo.require("dojox.dtl._Templated");
dojo.declare("demo", [dojox.dtl._Widget, dojox.dtl._Templated] {
templateString: "<div>I like eating {{ fruit }}</div>",
postCreate: function(){
this.fruit = "apple";
this.render();
}
});
|
上面的例子使用了文本方式,当然我们也可以使用 HTMLTemplate,只要将 dojox.dtl._Templated 替换成 dojox.dtl._HtmlTemplated 即可。同 dijit widget 一样,我们也可以使用 templatePath,templateString 指定模板,使用 dojoAttachPoint 和 dojoAttachEvent 指定节点与 JavaScript 交互的属性。另外也可以为 render 方法指定 context,否则会将当前的 widget 对象作为 context。下面的例子说明了如何用 dojox.dtl._HtmlTemplated 来创建 widget。
清单 5. HTML 模板示例
<html>
<head>
<title>dojo.DTL Demo</title>
<script type="text/javascript" src="dojo/dojo.js" djConfig="parseOnLoad: true">
</script>
<script type="text/javascript">
dojo.require("dijit.dijit");
dojo.require("dojox.dtl._HtmlTemplated");
dojo.require("dojo.parser");
dojo.declare("Fruit", [dijit._Widget, dojox.dtl._HtmlTemplated], {
oldRepl: "Fruit: ",
items: ["apple", "banana", "orange"],
keyUp: function(e){
if(e.keyCode == dojo.keys.ENTER){
var i = dojo.indexOf(this.items, e.target.value);
if(i != -1){
this.items.splice(i, 1);
}else{
this.items.push(e.target.value);
}
e.target.value = "";
this.render();
dojo.query("input", this.domNode).forEach("item.focus();");
}
},
templateString: '<div><input dojoAttachEvent="onkeyup: keyUp">
<ul>{% for item in items %}<li>{{oldRepl}} {{ item }}</li>{% endfor %}</ul>
</div>'
});
</script>
</head>
<body>
<div dojoType="Fruit"></div>
</body>
</html>
|
首先创建了 widget 类 Fruit,定义了变量 oldRepl 和数据 items,以及 keyUp 函数,这个函数通过 dojoAttachEvent 与模板里的 input 元素的 onkeyup 事件绑定。在 templateString 里定义了一个输入框和一个列表,通过 for 标签输出水果列表。
在浏览器里打开该文件,显示效果如下:
图 1. HTML 模板示例效果图
在输入框中输入水果名字,如果该水果名字在列表中已经存在,则从列表中删除该水果条目。如果列表中不存在该水果,则将该水果添加到列表中。
在 Web 开发中使用模板可以将页面展示和业务处理逻辑分离,降低模块之间的耦合,从而使系统更灵活,更能适应需求的改变,更易于维护。DojoX DTL 完全实现了 Django 模板语言的语法特性,并增加了对 HTML DOM 节点的支持。本文简要介绍了 DTL 的语法及 DojoX DTL 的使用,我们可以在 dojo.query 中或创建 widget,以及在任何需要输出数据改变而格式不变的地方使用 DojoX DTL。DojoX DTL 还有很多特性,如支持使用 DataStore 作为数据源,支持自定义标签和 filter,在开发中使用这些特性往往能起到事半功倍的作用。
- 参考 Django book,了解 Django Web 开发框架
- 参考 Django 标签库文档和 Django 过滤器文档,了解 Django 标签和过滤器语法
- 参考 DojoX DTL 官方文档,了解更多 DojoX DTL 信息
-
参考 Django book,了解 Django Web 开发框架。
-
参考 Django 标签库文档和 Django 过滤器文档,了解 Django 标签和过滤器语法。
-
参考 DojoX DTL 官方文档,了解更多 DojoX DTL 信息。
-
查看 其他关于 Dojo Toolkit 的在线文档。
- developerWorks 技术活动和网络广播:随时关注 developerWorks 技术活动和网络广播。
-
developerWorks Web development
专区:通过专门关于 Web 技术的文章和教程,扩展您在网站开发方面的技能。
