DOM模块
1、优化框架结构
1.1 简化存储DOM元素的容器 - elements
1.1.1 使用 elements 的优缺点:
- 优势:使得数据和方法分离,结构清晰明了
- 劣势:增加了使用数据的复杂度
1.1.2 jQuery中存储数据的容器
- 思路:直接把数据存储到 this 中
- 问题:如何jQuery对象转化为DOM对象?
1.2 使用this作为存储数据的容器
- 思路:直接使用this存储数据并提供 length 属性
- 问题:如何获取数据的个数?
- 修改:appendTo 去掉 elements
var itcast = function(selector) { return new itcast.prototype.init(); }; itcast.prototype = { constructor: itcast, length: 0, init: function(selector) { if(typeof selector === "string") { if(selector.charAt(0) === "<") { push.apply(this, parseHTML(selector)); } } } }; itcast.prototype.init.prototype = itcast.prototype;
2、增强 appendTo 方法的功能
- 目标:实现追加元素的功能并支持多种类型的参数
- 问题:参数处理的逻辑放在哪?
2.1 可能存在的参数类型
- 参数:字符串 / DOM对象 / DOM数组 / itcast对象
- 思路:保证参数被处理后获取到的是一个伪数组即可(不管参数的类型是什么)
2.2 回顾 appendTo 方法的实现
- 前提:假定参数为字符串(选择器或者html字符串)
- 思路:将字符串转化为 DOM对象数组
2.3 重新考虑 itcast 的参数
1 "" / null / undefined2 DOM对象3 DOM数组4 itcast对象5 fn6 string => 已经完成7 无参数
2.3.1 修改 itcast 函数参数
init: function(selector) { if(!selector) return this; if(itcast.isString(selector)) { if(selector.charAt(0) === "<") { itcast.push.apply(this, parseHTML(selector)); } else { itcast.push.apply(this, select(selector)); this.selector = selector; } } else if(itcast.isDOM(selector)) { this[0] = selector; this.length = 1; } else if(itcast.isItcast(selector)) { return selector; } else if(itcast.isLikeArray(selector)) { itcast.push.apply(this, selector); } }
3、实现 append 方法 和其他方法
3.1 append 方法实现
itcast.fn.extend({ append: function(selector) { itcast(selector).appendTo(this); } });
3.2 prependTo 方法实现
3.2.2 实现 prependTo
itcast.fn.extend({ prependTo: function(selector) { var tar = itcast(selector), i, j, tarLen = tar.length, srcLen = this.length; for(i = 0; i < tarLen; i++) { for(j = 0; j < srcLen; j++) { tar[i].insertBefore( i === tarLen - 1? this[j]: this[j].cloneNode(true), tar[i].firstChild ); } } } });
4、添加链式编程支持
4.1 回顾 jQuery 的链式编程
- 问题:如何实现链式编程?
- 注意:有些方法中返回的不是 this (appendTo方法)
4.2 给 appendTo 添加链式
itcast.fn.extend({ appendTo: function(dom) { // ... arr.push(node); // ... return itcast(arr); } });
4.3 创建实例方法 each
itcast.fn.extend({ each: function(callback) { return itcast.each(this, callback); } });
5、提供remove方法
itcast.fn.extend({ remove: function() { return this.each(function() { this.parentNode.removeChild(this); }); } });