本节书摘来自异步社区《Ext JS实战》一书中的第2章,第2.3节,作者:【美】Jesus Garcia著,更多章节内容可以访问云栖社区“异步社区”公众号查看
2.3 使用Template和XTemplate
Ext.Template是一个很强大的核心工具,借助它可以创建一个预先留好插槽的DOM层次结构,以后再用数据填补这些插槽。一旦定义好了模板,可以用它复制出一个或者多个预定义好的DOM结构,并用数据填充这些插槽。精通模板有助于用模板管理UI部件,例如GridPanel、DataView和ComboBox。
2.3.1 模板练习
先从创建一个相当简单的模板开始,然后继续创建一个更加复杂的模板。
这个例子中,创建了Ext.Template的一个实例,这个模板的内容是一个预留着插槽的div字符串,插槽就是一对大括号和它围起来的内容,这里使用变量myTpl引用这个模板。现在可以调用myTpl.append了,传给它的是目标元素document.body以及用来填充插槽的数据,在这个例子中就是一个只有一个元素的数组,数组的内容是姓名。
这里连续调了3次,结果就是在DOM中加了3个div,各自的插槽中填的都是不同的名字。图2-6所示的就是添加后的结果。
图2-6 用第一个模板给DOM添加节点后从Firebug中看到的结果
已经看到了,文档内容中添加了3个div,每个都有不同的名字。使用模板的好处显而易见。模板只需要设置一次,然后用不同的值填充到DOM中。
在前一个例子中,花括号里的插槽是个整数,传入的也是一个只有一个元素的数组。模板也可以用简单对象的key/value映射。下面这段代码就是创建了这样一个模板的语法,如代码2-1所示。
代码2-1 创建一个复杂的模板
对于这个复杂模板的创建代码1方法个dBodyment.htmlNodes[n])更费时事件首先注意到的可能是传入的是几个参数,这是因为在创建模板时,这种用tab分隔样式的伪HTML代码看起来要比一个长字符串容易阅读。Ext开发人员要喜欢这个方式, Template构造函数会接收所有的传入参数,而不管有多少个。
这个模板的伪HTML代码中,有4个数据点的槽位。第一个是color,这个用于元素的背景。其他3个数据点分别是name、age和dob,在添加这个模板时可以立即看到效果。
接着,对这个模板进行编译(Compile)2,这么做会通过减少正则表达式的开销加速不少。从技术上来说,就这么两个操作没有编译的必要,因为感觉不到速度上有什么好处,不过如果是一个大型的应用程序,里面可能会有很多的模板要填充,这时编译就很有用处了。出于安全起见,每次实例化之后我总是要对模板进行编译。
最后,调用了两次append3,同时传入了一个元素引用和数据对象。与在第一个模板示例中看到的不同,传入的不再是数组,而是一个数据对象,这个对象的键正好和模板中槽位相匹配。图2-7就显示了这个复杂的模板在Firebug的DOM视图中的效果。
图2-7 这个复杂的模板在Firebug的DOM视图中看到的效果
通过使用模板,可以得到两个不同风格的DOM元素。如果有一个对象数组该怎么办呢?例如,如果一个Ajax请求返回的是一个数据对象数组,难道要对每个数据对象使用模板吗?一个方法就是对数组进行遍历,一个普通的for循环就能做到这点,而更健壮的方式使用Ext.each方法。但我不会用这种方法,相反地我会使用XTemplate,这样代码会更加清晰。
2.3.2 用XTemplate循环
从技术上说,XTemplate也可以用于一个数据对象,不过用它循环处理一个数据数组会更容易。XTemplate本身也是扩展自Template,并且并且mplateebody功能更强。我们的探讨会从创建一个数据对象数组开始,然后创建一个XTemplate,再用后者生成一段HTML代码,如代码2-2所示。
代码2-2 使用XTemplate循环处理数据
在这段代码中,首先创建了一个数据对象数组1,这个数组和上一个模板中的数据对象类似,增加的cars也是个数组,接下来的例子就要用到这个数组。
接下来,创建了一个XTemplate的实例2,看起来和上一个模板的配置也很像,所不同的是用一个定制的tpl标签把div容器封装起来,这个tpl标签有个属性for,值是“. ”3。tpl标签相当于是模板的一个逻辑或行为修饰符,它有两个操作符,for和if,这两个操作符会调整XTemplate生成HTML内容的方式。在这个例子中,“. ”这个值告诉XTemplate从这个数组的根开始遍历,并按照tpl标签封装的伪HTML代码生成HTML内容。如果查看渲染后的HTML,会看到DOM中根本没有tpl标签。最后的结果和Template例子中是一样的,如图2-8所示。
记住,这个例子中使用XTemplate所带来的好处是不用再写循环遍历对象数组的代码了,这些工作都由框架替我们完成了。XTemplate的功能不仅仅是遍历数组,它的用途还很多。
2.3.3 XTemplate的高级用途
我们还可以通过配置XTemplate实现对数组内的数组的遍历,甚至可以加上条件逻辑。下面这段代码就演示了XTemplate的灵活程度,并演示了许多高级概念,如代码2-3所示。有些语法对你来说可能是陌生的。不要害怕,我会一一道来。
代码2-3 XTemplate的高级用途
这一部分用到了XTemplate的一些高级概念,第一个就是循环中的循环1。记住,for属性让XTemplate遍历一个列表。在这个例子中,for属性值是'cars',这不同于第一个属性值“. ”。这是告诉XTemplate对每一个car遍历这个伪HTML代码块。记住,cars本身也是一个字符串数组。
在这个循环中是一个“{.}”字符串,这其实是告诉XTemplate把对数组循环遍历所获得的当前值放到这里。简单地说,就是把car的名字放在这里。
接下来,看到的是一个带有if属性3的tpl行为修饰器,即传入values并执行this.isCamry。this.isCamry方法是在XTemplate的最后生成的5。这里我们多说一点。if属性很像是if条件,如果if条件能够满足,XTemplate就会产生HTML片段。就这个例子而言,要生成在tpl标签中的内容,this.isCamry必须返回true。
Values属性是对遍历的数组中的值的引用,由于遍历的是一个字符串数组,所以这个引用的就是一个字符串,也就是汽车的名字。
接下来同样执行任意的JavaScript代码4。凡是放在花括号和方括号({[…JS 代码]})里面的任何内容都会被当做普通的JavaScript;这些代码可以访问XTemplate提供的局部变量,而且可以在每次循环中修改它们。这个例子中,检查的是当前索引值(xindex)是否小于数组的元素个数(xcount),根据检查结果返回一个逗号空格或者一个空字符串。这个内联测试能够确保汽车名字的后面正确地加上逗号。
最后一个有趣的内容是带有isCamry方法的对象5。在XTemplate的构造器中传入一个带有若干成员的对象(或者对象引用),可以保证在这个XTemplate中可以直接使用这些成员。这也是为什么能在tpl的行为修饰符为元素if条件中可以直接使用this.isCamry。所有这些成员方法都是在它们所传入的XTemplate实例的作用域内调用的。这个概念非常强,不过也很危险,因为有可能会覆盖已有的XTemplate成员,因此一定要确保方法或者属性是唯一的。IsCamry方法用JavaScript的简写形式测试传入的字符串car,如果等于“Camry”则返回true,否则返回false。图2-9所示为这个高级XTemplate的结果。
这个高级XTemplate练习的结果显示,这里行为注入确实已经如愿以偿。所有的汽车都罗列出来了,逗号也正确地加上了。可以看到注入的JavaScript工作了,因为Camry的右侧被加上了“(some car)”。
就像所看到的,Template和XTemplate和普通的用Ext.Element填充HTML内容比较起来明显好得多。我建议你仔细地看一下Template和XTemplate的API文档,更详细地了解使用这些工具的例子。等后面谈到如何创建一个自定义的ComboBox时,还会探讨Template的用法。