作家
登录

prototype Element学习笔记(篇一)

作者: 来源:www.28hudong.com 2013-03-30 02:53:06 阅读 我要评论

先说一下Element对DOM扩展的技术思路,我也是看了一天的代码,这才有了点心得。 使用prototype,我们最常用的莫过于$('div1')之类的代码。从而获得扩展后的element对象,然后,我们就可以用它的各种扩展出来的方法了,如: $('div1').addClassName('loading').show(); 所以,我们研究Element的扩展正应当以此为入口。 function $(element) { if (arguments.length > 1) { for (var i = 0, elements = [], length = arguments.length; i < length; i++) elements.push($(arguments[i])); return elements; } if (Object.isString(element)) element = document.getElementById(element); return Element.extend(element); } 这个函数一个巧妙的递归就可以处理多个参数的情况,实在令我赞叹啊。代码中的关键是:Element.extend(element),在extend之前,element还仅仅是一个普通的DOM对象,extend之后就被扩展了,可见,秘密就在extend之中。 既然是Element.extend(element),那么,我们当然不能单独去研究extend,还是得先了解一下Element是何物。 (function() {    var element = this.Element;    this.Element = function(tagName, attributes) {      attributes = attributes || { };      tagName = tagName.toLowerCase();      var cache = Element.cache;      if (Prototype.Browser.IE && attributes.name) {        tagName = ' <' + tagName + ' name="' + attributes.name + '">';        delete attributes.name;        return Element.writeAttribute(document.createElement(tagName), attributes);      }      if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));      return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);    };    Object.extend(this.Element, element || { }); }).call(window); 这种代码比较有个性,基本结构是:(function(){……}).call(window);所以,看到这个结构,就要晓得,省略号部分出现的this都是指向window的。 var element=this.Element;这行不难理解,但是,关键是this.Element这时还没有被定义。后面则是定义一个类:window.Element类,它有两个参数:tagName、attributes。它的作用就是创建一个元素,并把一个纯洁的指定标签对应的DOM对象放入缓存。创建元素后,并且写入指定的属性值。这儿要提醒一下: writeAttribute、readAttribute这两个函数功能显然,读、写属性,但是,它的代码并不简单啊,它的复杂性主要源于不同的浏览器中,读、写属性的方法的不同。 这是Element类的构造函数的定义,它之后的Element.cache = { };缓存,什么的缓存,不大好描述,各种标签的纯洁版DOM元素对象的缓存?这话说得太恶心了。后面紧跟着就是一个:Element.Methods={……},在这里,几乎定义了所有的扩展方法。这里的扩展方法都有一个特征,代码中没有一个用this的,都是老老实实传进去一个element引用。这是一个伏笔,为什么要定义成这样,是有原因的。且容后交待。 现在Element大概说了一下,就得讲一讲Element.extend了。 Element.extend = (function() {    if (Prototype.BrowserFeatures.SpecificElementExtensions)      return Prototype.K;   var Methods = { }, ByTag = Element.Methods.ByTag;   var extend = Object.extend(function(element) {      if (!element || element._extendedByPrototype ||      element.nodeType != 1 || element == window) return element;     var methods = Object.clone(Methods),      tagName = element.tagName, property, value;     // extend methods for specific tags      if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);     for (property in methods) {        value = methods[property];        if (Object.isFunction(value) && !(property in element))          element[property] = value.methodize();      }     element._extendedByPrototype = Prototype.emptyFunction;      return element;   }, {       refresh: function() {        // extend methods for all tags (Safari doesn't need this)        if (!Prototype.BrowserFeatures.ElementExtensions) {          Object.extend(Methods, Element.Methods);          Object.extend(Methods, Element.Methods.Simulated);        }      }    });   extend.refresh();    return extend; })(); 第一行的原理我不大肯定,不说,下面的代码看似复杂,待我抽出它的大概结构来: var extend=Object.extend(function(element){……},{refresh:function(){……}}); extend内,第一个函数作用是从XXXX.Methods中获取方法,并复制到本element中。这儿主要基于这样的考虑: 一、元素如果是一个Form,就得从Form.Methods取方法 二、元素如果是表单内的可输入元素,就得从Form.Element中取方法 三、所有元素都应当从Element.Methods中取得通用方法(后面的refresh所考虑的)。 也就是说,这儿要考虑多种情况,本来应当是个if语句的事,但是,这儿巧妙地设计了一个Element.Methods.ByTag。从而解决了这个问题。 if (Object.isFunction(value) && !(property in element)) element[property] = value.methodize(); 如果Methods中的成员不是函数或者函数在element中已存在,则不会覆盖。这儿到了关键了,那个value.methodize(),这时,前面的伏笔生效了,methodize的作用就是把当前调用者传递进方法。且作为第一个参数传入。它的使用方法一般是: obj.methodname=functionname.methodize(); 这样,调用时,obj对象就会作为第一个参数传入functionsname这个函数。 到此为止,这个extend函数中的大概思路应当清晰了,现在还有一个问题没有清楚:根据元素的tagName来获得应当从哪个Methods获得扩展,那么,我们有必要了解一下ByTag的详情,查找一下,找到了: Object.extend(Element.Methods.ByTag, { "FORM": Object.clone(Form.Methods), "INPUT": Object.clone(Form.Element.Methods), "SELECT": Object.clone(Form.Element.Methods), "TEXTAREA": Object.clone(Form.Element.Methods) }); ok,差不多就这样了。

  推荐阅读

  javascript title闪动效果

[Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]>>>详细阅读


本文标题:prototype Element学习笔记(篇一)

地址:http://www.17bianji.com/kaifa2/JS/29289.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)