Prototype是怎样扩展DOM的

来源:互联网 发布:vb中tab是什么意思 编辑:程序博客网 时间:2024/05/17 04:21

Prototype框架最大的部分是他对DOM的扩展。Prototype给通过函数$()返回的元素增加了不少方便的方法。比如,你可以写$('comments').addClassName('active').show()来得到一个ID是ID 'comments'的元素,增加一个类名给这个元素,然后显示它(如果他原来是隐藏的)。这个'comments'元素在原来的javascript里是没有的这些方法的,那现在它是怎样实现的呢?这个文档展示了一些Prototype里面用到的聪明的办法。: q3 u) [3 F* M, t) T9 /+ U( C; U

Element.extend()方法
大部分的DOM访求是封装在Element.Methods对象里面的,然后复制到Element对象里面(为了方便起见)。它们都接收这个元素作为最初的参数。

复制内容到剪贴板
代码:
Element.hide('comments');
var div_height = Element.getHeight(my_div);
Element.addClassName('contactform', 'pending');

这些代码既简洁,可读性也好。但是我们还可以做的更好。如果你要得到一个元素去处理点东西,你可以通过Element.extend传过去,然后就可以复制所有的方法给这个元素了。例如,创建一个元素并控制它:

复制内容到剪贴板
代码:
var my_div = document.createElement('div');

Element.extend(my_div);
my_div.addClassName('pending').hide();

// insert it in the document
document.body.appendChild(my_div);

我们的方法调用变的更短也更直观。正如前面所提到的,Element.extend从Element.Methods复制所有的方法到我们的元素里,这个元素就自动的成为了所有这些函数的第一个变量。这个extend()方法很聪明,不会在同一个元素上执行两次。更好的是,美元函数会把每个转入的元素都用这种机制扩展起来。
另外,Element.extend() 也适用Form.Methods的FORM元素和Form.Element.Methods的INPUT,TEXTAREA和SELECT元素。

复制内容到剪贴板
代码:
var contact_data = $('contactform').serialize();
var search_terms = $('search_input').getValue();

要注意的是不只是美元函数自动扩展元素。Element.extend()在document.getElementsByClassName,,Form.getElements,从$$()函数(要匹配一个CSS选择器)返回的元素和其它地方都会被调用到。最后你可能根本不用显式的调用Element.extend()。) Y( i9 _# n( p' Z/ R

通过Element.addMethods()添加你自己的方法


如果你有一些自己的DOM方法想加到prototype上,那也完全没有问题。Prototype也提供了一个这样的机制。假设你有一串的函数封装在一个对象里,那么你只要把这个对象传给Element. addMethods():

复制内容到剪贴板
代码:
var MyUtils = {
     truncate: function(element, length){
         element = $(element);
         return element.update(element.innerHTML.truncate(length));
     },
     updateAndMark: function(element, html){
         return $(element).update(html).addClassName('updated');
     }
}

Element.addMethods(MyUtils);

// now you can:
$('explanation').truncate(100);

唯一一个值得注意的就是保证这些方法的第一个参数就是这个元素本身。在你的方法里,你也可以为了可链接性在最后返回这个元素(或者,象这个例子这样,任何方法本身返回这个元素)。

原生的扩展
在所有这些下面还隐藏了一个密秘。; A4 `0 s# X, j' ]7 T
+ ?+ ?! F9 M" R
在支持增加方法到象HTMLElement这样的原始对象的原型里的浏览器中,所有的对于DOM扩展默认都是可以的,你也不必调用Element.extend(),美元函数或者任何其它东西。下面的内容在这些浏览器里可以工作:

复制内容到剪贴板
代码:
var my_div = document.createElement('div');
my_div.addClassName('pending').hide();
document.body.appendChild(my_div);

因为原生浏览器对象的原型扩展了,所以所有的DOM元素就都有了这个内建的原型扩展方法了。然而这个在IE里却不行,因为它不允许你动HTMLElement的原型。为了使上面的例子在IE下面也能运行,你不得不用Element.extend()来扩展元素。不过不用担心,这个方法很聪明,不会对一个元素扩展两次。, O* {: K( G2 t# i

因为浏览器不支持,所以你必须在那小心使用DOM扩展,保证只在那些已经扩展了的元素上使用。例如,上面的例子在Firefox和Opera里可以工作,但是创建这个元素后加上Element.extend(my_div)就让这个脚本得到了增强。你可以象下面的例子一样使用美元函数做一个快捷方法:

复制内容到剪贴板
代码:
// this will error out in IE:
$('someElement').parentNode.hide()
// to make it cross-browser:
$($('someElement').parentNode).hide()

有一点不要忘记的,总是在你要支持的浏览器里充分的测试。