超赞的动手创建JavaScript框架的详细教程(4)

假设参数els是一个DOM对象。一个功能完备的DOM库应该能处理节点(node)或节点序列(nodelist),但现在我们不作要求。首先遍历需要被添加进的元素 (父元素),再在这个循环中遍历将被添加的元素 (子元素)。
    如果将一个子元素添加至多个父元素,需要克隆子元素(避免最后一次操作会移除上一次添加操作)。可是,没必要在初次添加的时候就克隆,只需要在其它循环中克隆就可以了。因此处理如下:
 

if (i > 0) { childEl = childEl.cloneNode(true); }

变量i来自外层forEach循环:它表示父级元素的序列号。第一个父元素添加的是子元素本身,而其他父元素添加的都是目标子元素的克隆。因为作为参数传入的子元素是未被克隆的,所以,当将单个子元素添加至单个父元素时,所有的节点都是可响应的。
最后,真正的添加元素操作:

parEl.appendChild(childEl);

因此,组合起来,我们得到以下实现:
 

Dome.prototype.append = function (els) { return this.forEach(function (parEl, i) { els.forEach(function (childEl) { if (i > 0) { childEl = childEl.cloneNode(true); } parEl.appendChild(childEl); }); }); };

prepend方法

我们按照相同的逻辑实现prepend方法,其实也相当简单。
 

Dome.prototype.prepend = function (els) { return this.forEach(function (parEl, i) { for (var j = els.length -1; j > -1; j--) { childEl = (i > 0) ? els[j].cloneNode(true) : els[j]; parEl.insertBefore(childEl, parEl.firstChild); } }); };

不同点在于添加多个元素时,添加后的顺序会被反转。所以不能采用forEach循环,而是用倒序的for循环代替。同样的,在添加至非第一个父元素时需克隆目标子元素。

第十一步: 删除节点

对于我们最后一个节点的操作方法,从dom中删除这些节点,很简单,只需要:

Dome.prototype.remove = function () { return this.forEach(function (el) { return el.parentNode.removeChild(el); }); };

只需要通过节点的迭代和在他们的父节点调用删除子节点方法。比较好的是这个dom对象依然正常工作(感谢文档对象模型吧)。我们可以在它上面使用我们想使用的方法,包括插入,预插回DOM,很漂亮,不是吗?

第12步:事件处理

最后,却是最重要的一环,我们要写几个事件处理函数。

如你所知,IE8依然使用旧的IE事件,因此我们需要为此作检测。同时,我们也要做好使用DOM 0 级事件的准备。

查看下面的方法,我们稍后会讨论:
 

Dome.prototype.on = (function () { if (document.addEventListener) { return function (evt, fn) { return this.forEach(function (el) { el.addEventListener(evt, fn, false); }); }; } else if (document.attachEvent) { return function (evt, fn) { return this.forEach(function (el) { el.attachEvent("on" + evt, fn); }); }; } else { return function (evt, fn) { return this.forEach(function (el) { el["on" + evt] = fn; }); }; } }());

在这里,我们用到了立即执行函数(IIFE),在函数内我们做了特性检测。如果document.addEventListener方法存在,我们就使用它;另外我们也检测document.attachEvent,如果没有就使用DOM 0级方法。请注意我们如何从立即执行函数中返回最终函数:其最后会被分配到Dome.prototype.on。在做特性检测时,与每次运行函数时检测相比,这样的方式分配适合的方法更加方便。

事件解绑方法off与on方法类似:.
 

Dome.prototype.off = (function () { if (document.removeEventListener) { return function (evt, fn) { return this.forEach(function (el) { el.removeEventListener(evt, fn, false); }); }; } else if (document.detachEvent) { return function (evt, fn) { return this.forEach(function (el) { el.detachEvent("on" + evt, fn); }); }; } else { return function (evt, fn) { return this.forEach(function (el) { el["on" + evt] = null; }); }; } }());

您可能感兴趣的文章:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgdjwz.html