关于js封装框架类库之DOM操作模块(二)
上一篇基本实现了框架结构,但是与真正能用上的项目框架比较还是存在很多不足,在这又做了些加强与优化
1 (function ( window, undefined ) { 2 3 4 var arr = [], 5 push = arr.push, 6 slice = arr.slice, 7 concat = arr.concat; 8 9 // 构造函数 10 var YY = function YY ( selector ) { 11 return new YY.fn.init( selector ); 12 }; 13 // 核心原型 14 YY.fn = YY.prototype = { 15 constructor: YY,//让原型结构保持不变 16 selector: null,//给其添加一个属性 17 length: 0,//原型中提供的属性,原型中不改值得情况下是共享的,修改后自己再次创建一个 18 // init 的参数可以有以下几种情况 19 // 1> null, "", undefined 20 // 2> fn 21 // 3> string (已经实现) 22 // 4> DOM 数组 23 // 5> DOM 对象 24 // 6> YY 对象 25 init: function ( selector ) { 26 27 if ( !selector ) return this; 28 29 // 兼容字符串: 选择器, html 30 if ( YY.isString( selector ) ) { 31 if ( selector.charAt( 0 ) === '<' ) { 32 // this.elements = parseHTML( selector );//在对象中直接绑定个属性,来储存数据,方法与其并列,方法与数据分离,维护简单,管理简单,但是在基于它的开发显得繁琐,简化elements:将数据直接储存在this中,即将YY当作伪数组 33 YY.push.apply( this, parseHTML( selector ) ); 34 } else { 35 // this.elements = select( selector ); 36 YY.push.apply( this, select( selector ) ); 37 this.selector = selector;//放在其他地方创建的对象没有此属性,那么可以去原型判断 38 } 39 //this.length = 0;//当没有搜索到元素时,无须给其添加length,直接共享原型中的属性,原型中添加length属性比较优,两者没有实质的差别 40 return this; 41 } 42 43 // 兼容DOM 对象 44 if ( YY.isDOM( selector ) ) { 45 this[ 0 ] = selector;//当前对象的一个元素 46 this.length = 1; 47 return this; 48 } 49 50 // 兼容YY 对象 51 if ( YY.isYY( selector ) ) { 52 return selector; 53 } 54 55 // 兼容DOM 数组(最后判断) 56 if ( YY.isLikeArray( selector ) ) { 57 YY.push.apply( this, selector );//每个元素放在当前对象中 58 59 return this; 60 } 61 },
//each 方法 62 each: function (callback){ 63 YY.each(this,callback);//当前每个元素(dom对象)都被回调函数作用 64 return this; 65 } 66 67 }; 68 YY.fn.init.prototype = YY.prototype; 69 70 // 可扩展 71 YY.extend = YY.fn.extend = function ( obj ) { 72 // 将 obj 的成员加到 this 上 73 var k; 74 for ( k in obj ) { 75 this[ k ] = obj[ k ]; 76 } 77 }; 78 79 var select = function ( selector ) { 80 var first = selector.charAt( 0 ), arr = [],node; 81 if ( first === '#' ) {//如果没有搜索到元素,空也加进了数组,所以要对其进行判断 82 //arr.push.call( arr, document.getElementById( selector.slice( 1 ) ) ) 83 node = document.getElementById( selector.slice( 1 ) ); 84 if ( node ) { 85 arr.push.call( arr, node ); // [ null ] 86 } else { 87 return null; 88 } 89 } else if ( first === '.' ) { 90 arr.push.apply( arr, document.getElementsByClassName( selector.slice( 1 ) ) ) 91 } else { 92 arr.push.apply( arr, document.getElementsByTagName( selector ) ); 93 } 94 return arr; 95 }; 96 97 var parseHTML = function ( html ) { 98 var div = document.createElement( 'div' ), 99 arr = [], i; 100 div.innerHTML = html; 101 for ( i = 0; i < div.childNodes.length; i++ ) { 102 arr.push( div.childNodes[ i ] ); 103 } 104 return arr; 105 }; 106 107 // 基本的工具方法 108 YY.extend({ 109 each: function ( arr, fn ) { 110 var i, l = arr.length, 111 isArray = YY.isLikeArray( arr ); 112 if ( isArray ) { 113 // 数组 114 for ( i = 0; i < l; i++ ) { 115 if ( fn.call( arr[ i ], i, arr[ i ] ) === false ) { 116 break; 117 } 118 } 119 } else { 120 // 对象 121 for ( i in arr ) { 122 if ( fn.call( arr[ i ], i, arr[ i ] ) === false ) { 123 break; 124 } 125 } 126 } 127 return arr; 128 }, 129 push: push 130 }); 131 YY.extend({ 132 firstChild: function (dom){ 133 var node,i,l = dom.childNodes.length; 134 for(i = 0;i < 1;i++){ 135 node = dom.childNodes[i]; 136 if(node.nodeType === 1){ 137 return node; 138 } 139 } 140 } 141 }); 142 143 144 // 判断类型的方法 145 YY.extend({ 146 isFunction: function ( obj ) { 147 return typeof obj === 'function'; 148 }, 149 isString: function ( obj ) { 150 return typeof obj === 'string'; 151 }, 152 isLikeArray: function ( obj ) { 153 return obj && obj.length && obj.length >= 0; 154 }, 155 isYY: function ( obj ) { 156 return 'selector' in obj;//判断对象原型中有无此属性来判断是否为YY对象 157 // 'selector' in obj 158 // obj.hasOwnProperty( 'selector' ) 159 // return obj.constructor.name === 'YY'; 160 }, 161 isDOM: function ( obj ) { 162 return !!obj.nodeType; 163 } 164 }); 165 166 167 // 基本的 DOM 操作 168 YY.fn.extend({ 169 appendTo: function ( selector ) { 170 var objs = YY( selector ), 171 i, j, 172 len1 = objs.length, 173 len2 = this.length, 174 arr = [],node; 175 // 将 this 加到 objs 中 176 for ( i = 0; i < len1; i++ ) { 177 for ( j = 0; j < len2; j++ ) { 178 node = i === len1 - 1 ? 179 this[ j ] : 180 this[ j ].cloneNode( true ); 181 arr.push(node); 182 objs[ i ].appendChild( ); 183 } 184 } 185 return YY(arr);//注意返回的对象 186 }, 187 188 append: function (selector){ 189 YY(selector).appendTo(this); 190 return this; 191 }, 192 prependTo: function(selector){ 193 //insertBefore(新元素,参考元素) 194 195 var objs = YY(selector), 196 i,j, 197 len1 = this.length; 198 len2 = objs.lenght; 199 for(i = 0;i < len2;i++){ 200 for(j = 0;j < len1;j++){ 201 objs[i].insertBefore(i ===len2 - 1? 202 this[j]: 203 this[j].cloneNode(true), 204 YY.firstChild); 205 } 206 } 207 return this; 208 }, 209 remove: function(){} 210 }); 211 212 213 214 215 // 对外公开 216 window.I = window.YY = YY; 217 218 })( window );
对以上函数封装为dom.js文件
1、验证appendTo方法代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> #login { width: 540px; height: 340px; background-color: gray; margin: 80px auto; padding: 30px; } </style> <script src="dom.js"></script> <script> onload = function () { I( '#loginBtn' )[ 0 ].onclick = function ( e ) { if ( I( '#login' ).length > 0 ) return; // alert( e ); // 弹出一个登录窗口 var ilogin = I( '<div id="login"></div>' ); ilogin.appendTo( 'body' ); // 设计内部的结构 I( '<input type="text" id="uid"/><br />' + '<input type="password" id="pwd"/><br />' + '<input type="button" value="登 录" id="btn"/><br />' + '<input type="button" value="取消" id="cancel"/>' ).appendTo( ilogin ); I('#cancel')[ 0 ].onclick = function () { var node = I( '#login' )[ 0 ]; node.parentNode.removeChild( node ); }; }; }; </script> </head> <body> <input type="button" value="登录" id="loginBtn" /> </body> </html>
2、验证append方法代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> #login { width: 540px; height: 340px; background-color: gray; margin: 80px auto; padding: 30px; } </style> <script src="dom.js"></script> <script> onload = function () { I( '#loginBtn' )[ 0 ].onclick = function ( e ) { if ( I( '#login' ).length > 0 ) return; // alert( e ); // 弹出一个登录窗口 var ilogin = I( '<div id="login"></div>' ); I( 'body' ).append( ilogin ); // 设计内部的结构 ilogin.append( '<input type="text" id="uid"/><br />' + '<input type="password" id="pwd"/><br />' + '<input type="button" value="登 录" id="btn"/><br />' + '<input type="button" value="取消" id="cancel"/>' ); I('#cancel')[ 0 ].onclick = function () { var node = I( '#login' )[ 0 ]; node.parentNode.removeChild( node ); }; }; }; </script> </head> <body> <input type="button" value="登录" id="loginBtn" /> </body> </html>
3、验证prependTo方法代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> #login { width: 540px; height: 340px; background-color: gray; margin: 80px auto; padding: 30px; } </style> <script src="dom.js"></script> <script> onload = function () { I( '<p>YY</p>' ).prependTo( 'div' ); }; </script> </head> <body> <div> <p>hellow world</p> <p>hellow YY</p> </div> <div> <p>hellow world</p> <p>hellow YY</p> </div> </body> </html>
方法待续,感谢您的查阅