教程:使用DomHelper 创建元素的DOM、HTML片断和模版

今晚我对prototype+Scriptaculous和 MochiKit's那个不错的DOM处理库进行的轮流测试,测试结果让我感觉好几次的意外。 读者可自行分析一下的成绩,结果很难令人信服。

在JavaScript的开发过程,某些原因你需要用DOM来创建元素。处理这些元素很可能会是一段又长有臃肿的代码,花费了不少时间而仅仅只是干一些鸡毛蒜皮的话,那就不值了。而且,用DOM创建这些元素的性能上并不高效,尤其是IE上面。要想即高效又能支持标准的话,任何DOM的创建类都应该支持DOM和HTML片断。HTML片断在IE中跑得很快,最快可跑到比原来快300%的速度。包含在版本 0.32.2中,那个可提取DOM层的DomHelper,就能通过DOM创建元素,或HTML片断,也能把你的DOM代码变成HTML片断的模版。

简单的例子
为了让我少打点字,下面的的例子假设有这么一个变量dh,就是代表了YAHOO.ext.DomHelper。

var dh = YAHOO.ext.DomHelper;我们看看这个简单例子: 

// 元素’my-div’可以是一个ID或某个实际节点
var list = dh.append('my-div', {tag: 'ul', cls: 'my-list'});

上面说了DomHelper能处理DOM或HTML片断,这用起来很方便,好像这样子便是添加了一个元素。这是一个极好的功能,而你不必像以前那样,新建它再加入内容。让我们把这个例子摊开来看:
var list = dh.append('my-div', {
 
	tag: 'ul', cls: 'my-list', children: [
 
	{tag: 'li', id: 'item0', html: 'List Item 0'}, 
 
	{tag: 'li', id: 'item1', html: 'List Item 1'}, 
 
	{tag: 'li', id: 'item2', html: 'List Item 2'}, 
 
	{tag: 'li', id: 'item3', html: 'List Item 3'}, 
 
	{tag: 'li', id: 'item4', html: 'List Item 4'}
 
	]
});

传递到对象“o”的所有属性都假设为元素的节点,除了下面四个属性: tag –元素的名称 children -对象的定义是数组类型,包含有相同特征的一类元素。 这里你可尽情地嵌套 cls - 元素的class属性。Class是一个保留字,className又太长了。 html – 元素的innerHTML

下列是一些插入方法:

append( el,o)- Creates new DOM element(s) defined by o and appends them to el
insertBefore( el,o)- Creates new DOM element(s) defined by o and inserts them before el
insertAfter( el,o)- Creates new DOM element(s) defined by o and inserts them after el
overwrite( el,o)- Creates new DOM element(s) defined by o and overwrites the contents of el with them
createTemplate(o)- Creates a template from the DOM element(s) defined by o (See below)
insertHtml( where, el, html) - Inserts fragments into the DOM. It supports four insertion points related to el (which are named after the same points in IE's insertAdjacentHTML): beforeBegin, afterBegin, beforeEnd, afterEnd.
嗯 我已经明白这些了,还要什么特别要注意的吗? 使用上述方法创建你的元素,DomHelper会尽可能地使用HTML片断,这会比DOM操作带来性能上极大的提升。但你不想这样的话,可强制使用DOM:

YAHOO.ext.DomHelper.useDom = true;

真正强大的是内建 版。“o”这个参数与其它所有方法一样,有相同的语法,但用在createTemplate()的时候,它不会创建或添加任何元素。插入这个元素会返回一个反复循环产生新元素的模版对象。让我们对比一下上面的例子,然后这次使用模版:
var list = dh.append('my-div', {
    tag: 'ul',
    cls: 'my-list'
});
var tpl = dh.createTemplate({
    tag: 'li',
    id: 'item{0}',
    html: 'List Item {0}'
});
for (var i = 0; i < 5; i++) {
    tpl.append(list, [i]);
}

模版对象支持相同的DomHelper插入方式。第二个插入方法的参数既可以是数组array(像上面的例子就是数字式的模版参数) 或一个对象(命名式参数) 模版对象也可以这样子用:
var html = '{2}';
var tpl = new YAHOO.ext.DomHelper.Template(html);
tpl.append('blog-roll', ['link1', 'http://www.jackslocum.com/', "Jack's Site"]);
tpl.append('blog-roll', ['link2', 'http://www.dustindiaz.com/', "Dustin's Site"]);同一个例子,不过是(named parameters)的: 

var html = '{text}';
 
var tpl = new YAHOO.ext.DomHelper.Template(html);
tpl.append('blog-roll', {
    id: 'link1',
    url: 'http://www.jackslocum.com/',
    text: "Jack's Site"
});
tpl.append('blog-roll', {
    id: 'link2',
    url: 'http://www.dustindiaz.com/',
    text: "Dustin's Site"
}); 

编译模版
在模版中用正则表达式可能不会让你意外。当前的性能已经不错了,但若然你有一大捆的DOM元素要加入的话,“编译”那个模版更能提升性能。The way "compile()" works is the template is parsed and broken up at the different variable points and a dynamic function is created and eval'ed. The generated function performs string concatenation of these parts and the passed variables instead of using regular expressions.
var html = '{text}';
var tpl = new YAHOO.ext.DomHelper.Template(html);tpl.compile();
//... use template like normal

基准测试
我做了一些基准测试,看看各种方式的区别。在循环1000次的产生3000个元素的循环中,执行了下面的代码,同样,对不用模版也进行了测试。
var spec = {
    tag: 'div',
    style: 'width:100%;border:1px solid blue;',
    cls: 'wtf',
    children: [{
        tag: 'a',
        href: '{url}',
        children: [{
            tag: 'span',
            html: '{text}'
        }]
    }]
};
var template = YAHOO.ext.DomHelper.createTemplate(spec);

下面是浏览器的平均时间。注意IE6的极大分别,从1.35到.300。这样的性能真令人觉得IE6的执行DOM的组件是用VB写的。Opera9的成绩始终是保持得最好的,

Author: Jack Slocum (译者:Frank Cheung)

Retrieved from "http://extjs.com/learn/Tutorial:%E4%BD%BF%E7%94%A8DomHelper_%E5%88%9B%E5%BB%BA%E5%85%83%E7%B4%A0%E7%9A%84DOM%E3%80%81HTML%E7%89%87%E6%96%AD%E5%92%8C%E6%A8%A1%E7%89%88"