Skip to content

Latest commit

 

History

History
500 lines (387 loc) · 12 KB

01 summary.md

File metadata and controls

500 lines (387 loc) · 12 KB

封装each方法: // 如果利用 get 方法获得多个元素的话, 就会得到多个数组 // 为了简化开发, 可以考虑将其合并到一个数组中 // 调用多次 get 方法, 如果想要多个数组就可以使用多个数组 // 想要一个数组, 就得到一个数组 var getTag = function(tag, results) { results = results || []; results.push.apply(results, document.getElementsByTagName(tag)); return results; } var each = function(arr, fn) { for (var i = 0; i < arr.length; i++) { if (fn.call(arr[i], i, arr[i]) === false) { break; } } } /* var list1 = getTag( 'div' ); var list2 = getTag( 'p' );

each( list1, function () {
	this.style.backgroundColor = 'orange';
});
each( list2, function () {
	this.style.backgroundColor = 'orange';
});		
*/

each(getTag('p', getTag('div')), function(i, v) { this.style.backgroundColor = 'red'; })

浏览器性能检测: var support = {};

		// support.getElementsByClassName = !!document.getElementsByClassName;
		// 在 jq 中不仅判断他是否存在, 还要判断其能力是否符合要求
		
		support.getElementsByClassName = (function () {
			
			var isExist = !!document.getElementsByClassName;
			
			if ( isExist && typeof document.getElementsByClassName == 'function' ) {
				// 自己创建一些元素, 并且加上 class 属性, 看是否可以获得到加上的所有元素
				var div = document.createElement( 'div' ),
					divWithClass = document.createElement( 'div' );
				
				divWithClass.className = 'c';
				div.appendChild( divWithClass );
				return div.getElementsByClassName( 'c' )[ 0 ] === divWithClass;
			
			}
			
			return false;
		})();
		
		
		if ( support.getElementsByClassName ) {
			// return node.getElementsByClassName( className );
			alert( '支持 class' );
		} else {
			// 自己实现( className );
			alert( '不支持 class' );
		}

common.js -- 00 var myPush = function( target, els ) { var j = target.length, i = 0; // Can't trust NodeList.length while ( (target[j++] = els[i++]) ) {} target.length = j - 1; };

// 注释: 对基本方法的封装 var getTag = function ( tag, context, results ) { results = results || []; try { results.push.apply( results, context.getElementsByTagName( tag ) ); } catch ( e ) { myPush( results, context.getElementsByTagName( tag ) ); }

return results;

};

var getId = function ( id, results ) { results = results || []; results.push( document.getElementById( id ) ); return results; };

var getClass = function ( className, context, results ) { results = results || [];

if ( document.getElementsByClassName ) {
	results.push.apply( results, context.getElementsByClassName( className ) );
} else {
	each( getTag( '*', context ), function ( i, v ) {
		if ( ( ' ' + v.className + ' ' )
					.indexOf( ' ' + className + ' ' ) != -1 ) {
			results.push( v );
		}
	} );
}
return results;

};

// 对循环的封装 var each = function ( arr, fn ) { for ( var i = 0; i < arr.length; i++ ) { if ( fn.call( arr[ i ], i, arr[ i ] ) === false ) { break; } } };

// 通用的方法 var get = function ( selector, context, results ) { results = results || []; context = context || document; // 1 2 3 4 var rquickExpr = /^(?:#([\w-]+)|.([\w-]+)|([\w]+)|(*))$/, m = rquickExpr.exec( selector );

if ( m ) {
	if ( context.nodeType ) {
		context = [ context ];
	}
	// 如果 context 是一个 dom 数组就没有问题了
	// 但是 context 是一个选择器字符串. 有可能是 '.c'
	// 
	if ( typeof context == 'string' ) {
		context = get( context );
	}
	each( context, function ( i, v ) {
		if ( m[ 1 ] ) {
			results = getId( m[ 1 ], results );
		} else if ( m[ 2 ] ) {
			results = getClass( m[ 2 ], v, results );
		} else if ( m[ 3 ] ) {
			results = getTag( m[ 3 ], this, results );
		} else if ( m[ 4 ] ) {
			results = getTag( m[ 4 ], this, results );
		}
	} );
}

return results;

};

选择器部分的封装 select.js // xxxxx // 选择器引擎

var select =

(function () {

var myPush = function( target, els ) { var j = target.length, i = 0; // Can't trust NodeList.length while ( (target[j++] = els[i++]) ) {} target.length = j - 1; };

// 注释: 对基本方法的封装 var getTag = function ( tag, context, results ) { results = results || []; try { results.push.apply( results, context.getElementsByTagName( tag ) ); } catch ( e ) { myPush( results, context.getElementsByTagName( tag ) ); }

return results;

};

var getId = function ( id, results ) { results = results || []; results.push( document.getElementById( id ) ); return results; };

var getClass = function ( className, context, results ) { results = results || [];

if ( document.getElementsByClassName ) {
	results.push.apply( results, context.getElementsByClassName( className ) );
} else {
	each( getTag( '*', context ), function ( i, v ) {
		if ( ( ' ' + v.className + ' ' )
					.indexOf( ' ' + className + ' ' ) != -1 ) {
			results.push( v );
		}
	} );
}
return results;

};

// 对循环的封装 var each = function ( arr, fn ) { for ( var i = 0; i < arr.length; i++ ) { if ( fn.call( arr[ i ], i, arr[ i ] ) === false ) { break; } } };

// 通用的方法 var get = function ( selector, context, results ) { results = results || []; context = context || document; // 1 2 3 4 var rquickExpr = /^(?:#([\w-]+)|.([\w-]+)|([\w]+)|(*))$/, m = rquickExpr.exec( selector );

if ( m ) {
	if ( context.nodeType ) {
		context = [ context ];
	}
	// 如果 context 是一个 dom 数组就没有问题了
	// 但是 context 是一个选择器字符串. 有可能是 '.c'
	// 
	if ( typeof context == 'string' ) {
		context = get( context );
	}
	each( context, function ( i, v ) {
		if ( m[ 1 ] ) {
			results = getId( m[ 1 ], results );
		} else if ( m[ 2 ] ) {
			results = getClass( m[ 2 ], v, results );
		} else if ( m[ 3 ] ) {
			results = getTag( m[ 3 ], this, results );
		} else if ( m[ 4 ] ) {
			results = getTag( m[ 4 ], this, results );
		}
	} );
}

return results;

};

var myTrim = function ( str ) { if ( String.prototype.trim ) { return str.trim(); } else { return str.replace( /^\s+|\s+$/g, '' ); } };

var select = function ( selector, context, results ) { results = results || []; // 首先处理逗号 var newSelectors = selector.split( ',' ); // => [ '.dv .c1', ' .c2' ] each( newSelectors, function ( i, v ) {

	// 需要解析的就是 v 或 this
	// 分割
	var list = v.split( ' ' );
	var c = context;
	// context -> list[ 0 ] -> list[ 1 ] -> ... -> list[ length - 1 ]
	for ( var i = 0; i < list.length; i++ ) {
		if ( list[ i ] === '' ) continue; 
		c = get( list[ i ], c );
		// 如果 list[ i ] 是空字符串, 那么只是下 c 下面找空数据, 是不会报错的
	}
	
	
	results.push.apply( results, c );
	
} );

return results;

};

return select;

})();

DOM模块 核心模型 // createElement 可以创建 HTML 的 DOM 对象

    // <DOM 对象>.appendTo( ... )

    // 原则: 不要直接的修改原生的内置对象的成员

    // 也就是说 DOM 对象不应该提供 appendTo 方法

    // 谁添加该方法?
    // -> DOM对象		错误
    // -> 原型对象		jq 对象的原型对象; 包装对象( 自定义对象 )的原型对象
    // -> jq 对象

    // $( '...' ).appendTo( $( 'body' ) )
    // 框架的结构
    //			var ana = function ( selector ) {
    //				return new F( selector );
    //			};
    //			var F = function ( selector ) {
    //				
    //			};
    //			F.prototype = {
    //				appendTo: function( selector ) {}
    //			};

    // 缺点???
    // 首先在沙箱中 F 对外不可见, 无法实现扩展
    // 同时在描述中容易造成多个变量暴漏与全局中

    // 解决方案, 直接将 F 绑定到 ana 的上面
    // -> ana.init = F
    // -> ana.prototype.init = F
    // 如果想要扩展
    // -> ana.init.prototype.xx = xxx;

    // 由于在方法中提供的方法一般是静态方法, 作为工具使用
    // 但是 jq 中并不是如此操作
    // 同时根据代码的组织规范, 初始化方法放在原型中更加合理( 与实例相关 )

    var ana = function(selector) {
        return new ana.prototype.init(selector);
    };
    ana.prototype = {
        appendTo: function(selector) {},
        init: function(selector) {}
    };

    ana.prototype.init.prototype = ana.prototype; 

节点复制: // 将问题简化 I( '

' ).appendTo( 'div' );

		// 将一个 div 数组( 2 个元素 ) 添加到 页面中的 div 中( 2 个 )
		// [ d1, d2 ]						[ div1, div2 ]
		// 将 d1 加到 div1 和 div2 中
		// 将 d2 加到 div1 和 div2 中
		
		// 单个元素要克隆几个由需要添加的元素个数决定, 刚刚是需要添加的个数 - 1
		
		// 再简化
		// 将 dv 加到 [ div1, div2, div3 ] 中
		/*
		div1.appendChild( dv.cloneNode( true ) );
		div2.appendChild( dv.cloneNode( true ) );
		div3.appendChild( dv );
		*/
		
		// 最后一个不克隆, 前面的所有都要克隆
		/*
		for ( var i = 0; i < list.length; i++ ) {
			list[ i ].appendChild( i === list.length - 1 ?
									dv : 
									dv.cloneNode( true ) );
		}
		*/
		
		
		
		// 接下来讨论两个循环
		// ds = [ d1, d2 ]						list = [ div1, div2, dv3 ]
		div1.appendChild( d1.cloneNode( true ) );
		div1.appendChild( d2.cloneNode( true ) );
		
		div2.appendChild( d1.cloneNode( true )  );
		div2.appendChild( d2.cloneNode( true )  );
		
		div3.appendChild( d1 );
		div3.appendChild( d2 );
		
		// 添加一层循环
		for ( var i = 0; i < ds.length; i++ ) {
			div1.appendChild( ds[ i ].cloneNode( true ) );
		}
		for ( var i = 0; i < ds.length; i++ ) {
			div2.appendChild( ds[ i ].cloneNode( true ) );
		}
		for ( var i = 0; i < ds.length; i++ ) {
			div3.appendChild( ds[ i ] );
		}
		// 合并
		for ( var j = 0; j < list.length; j++ ) {
			for ( var i = 0; i < ds.length; i++ ) {
				list[ j ].appendChild( j === list.length - 1 ? 
											ds[ i ] : 
											ds[ i ].cloneNode( true ) );
			}
		}

创建子节点的问题: // jq 中 // $( '

' );

// itcast -> I // var dom = I( '一个链接' )

var cElem = function(html) { // 1, 在内部创建一个 docfrag var docfrag = document.createDocumentFragment(); // 2, 创建真正的 div, 然后设置其 innerHTMl 为出入的字符串 // 然后在遍历该子元素, 将内容加入到 docfrag 中 var div = document.createElement('div'); // 3, 将字符串设置为 它的 innerHTML div.innerHTML = html; // 4, 遍历div的子元素, 加入 docfrag // 在 DOM 元素中默认有一个特征, 即元素只允许有一个 父节点 // 如果添加元素到另一个节点中, 该元素会自动的离开原来的父节点 while (div.firstChild) { docfrag.appendChild(div.firstChild); } // 5, 获得其子元素返回 return docfrag; }; 以下是理解方式:

<title></title> <script type="text/javascript">
		var id = function ( id ) {
			return document.getElementById( id );
		};
		
		
		onload = function () {
			var d1 = id( 'dv1' );
			var d2 = id( 'dv2' );
			var list = d1.getElementsByTagName("p");
			var len;

// for ( var i = 0, len = list.length; i < len; i++ ) { // // d2.appendChild( list[ 0 ] ); // // }

// while ( list[ 0 ] ) { // d2.appendChild( list[ 0 ] ); // }

			while ( d1.firstChild ) {
				d2.appendChild( d1.firstChild );
			}
		};
		
	</script>
</head>
<body>
	<div id="dv1">
		<p>p1</p>
		<p>p2</p>
		<p>p3</p>
		<p>p4</p>
	</div>
	<div id="dv2">
		
	</div>
</body>