jquery - DOM操作
核心框架成员
核心成员
1> selector 用来存储该 itcast 对象的选择器
2> toArray 方法
3> get 方法
4> each 与 map 方法
5> eq 方法
selector 和 toArray
selector
凡是使用选择器获得元素来创建的 jq 对象都有 selector 属性
凡是使用 jq 对象创建 jq 对象都有 该属性
其实就是为了说明该元素是使用 指定的选择器获取到的.
我们只需要在使用选择器创建的对象时来添加即可
在 jq 中还使用 该属性来判断 对象是否为 jq 对象
我们实现对其简化:
1) 提供一个 selector 表示 选择器
2) 提供一个 type 属性, 存储 'jepson'. 用来表示对象是否为 jepson 类型
toArray
将 jq 对象中的每一个元素取出来组成一个数组返回
var res = [];
for ( ... ) {
res.push( ... )
}
jepson.fn = jepson.prototype = {
constructor: jepson,
length: 0,
selector: '', // 表示使用了选择器
type: 'jepson', // 标记对象类型
init: function (html) {
// 如果是空对象 或者 空字符串
if (html == null || html == '') return; // 直接结束
// 如果是函数
if (typeof html == 'function') {
// do something
}
// 如果是字符串
if ( jepson.isString(html) ) {
// 看是不是标签字符串
if ( /^</.test( html ) ) {
// 是就转换成 dom 对象伪数组 分别 push 到 this 对象中
push.apply( this, parseHTML( html ) );
} else {
// 不是就是选择器,选中页面中的 dom 对象伪数组 分别 push 到this对象中
push.apply( this, jepson.select( html ) );
// 是选择器,就给他加上 selector 属性
this.selector = html;
}
}
// 如果是 jepson 对象
if ( html && html.type === 'jepson' ) {
// 是 jepson 对象
// 将传入 的 jepson 对象所有的元素都 添加到 this 中
push.apply( this, html );
this.selector = html.selector;
}
},
toArray: function () {
var res = [];
for ( var i = 0; i < this.length; i++ ) {
res.push( this[ i ] );
}
return res;
}
}
get方法, 就是利用 toArray先转换成dom数组
jepson.fn = jepson.prototype = {
constructor: jepson,
length: 0,
selector: '', // 表示使用了选择器
type: 'jepson', // 标记对象类型
init: function (html) {
...
},
toArray: function () {
var res = [];
for ( var i = 0; i < this.length; i++ ) {
res.push( this[ i ] );
}
return res;
},
get: function( index ) {
if ( index === undefined ) {
return this.toArray();
}
return this[ index ];
}
}
eq 方法, $.eq(num)
$.eq(num)
num >= 0 正向取
num < 0 倒着取, 使用 length + num 获得元素 返回 jquery 对象
没找到不传参返回空 jquery 对象
jepson.fn = jepson.prototype = {
constructor: jepson,
length: 0,
selector: '', // 表示使用了选择器
type: 'jepson', // 标记对象类型
init: function (html) {
// 如果是空对象 或者 空字符串
...
// 如果是字符串
...
// 如果是 jepson 对象
...
// 判断是不是一个 DOM 对象, DOM 对象 有 nodeType 属性
if ( html.nodeType ) {
this[ 0 ] = html;
}
},
toArray: function () { // 注意返回 dom 对象数组
...
},
get: function( index ) { // 注意返回 dom 对象
...
},
eq: function ( num ) {
var dom;
// 这里要做判断 num >= 0 正向取 num < 0 倒着取
if ( num >= 0 ) {
dom = this.get( num );
} else {
dom = this.get( this.length + num );
}
// 这里要么是 undefined,要么就是 dom 对象, 调用自己的构造函数来构造
return this.constructor( dom );
}
}
each 和 map 方法
// 需要一些公共,共有方法,函数对象的方法,通过 extend 添加进来
jepson.extend( {
each: function ( arr, func ) {
var i;
// 在 ES5 中还引入了 Array.isArray 的方法专门来判断数组
if ( arr instanceof Array || arr.length >= 0 ) {
for ( i = 0; i < arr.length; i++ ) {
// 方法借调,让 arr[ i ] 成为宿主对象
func.call( arr[ i ], i, arr[ i ] );
}
} else {
for ( i in arr ) {
func.call( arr[ i ], i, arr[ i ] );
}
}
return arr;
},
map: function ( arr, func ) {
var i, res = [], tmp;
if ( arr instanceof Array || arr.length >= 0 ) {
for ( i = 0; i < arr.length; i++ ) {
tmp = func( arr[i], i );
if ( tmp != null ) {
res.push( tmp );
}
}
} else {
for ( i in arr ) {
tmp = func( arr[ i ], i );
if ( tmp != null ) {
res.push( tmp );
}
}
}
return res;
}
});
利用给对象函数扩展的 map 和 each 的静态方法, 我们给实例对象添加原型方法
jepson.fn = jepson.prototype = {
constructor: jepson,
length: 0,
selector: '', // 表示使用了选择器
type: 'jepson', // 标记对象类型
init: ...,
toArray: ...,
get: ...,
eq: ...,
each: function ( func ) {
// 将 this 中的每一个 dom 元素遍历一下
return jepson.each( this, func );
},
map: function( func ) {
return jepson.map( this, func );
}
}
使用 slice 对 toArray 进行优化
slice 方法
获得数组的子元素, 且不会改变原数组
arr.slice( startIndex ); // 从 startIndex 取到尾
arr.slice( startIndex, endIndex );
拷贝数据获得数组
arr.slice( 0 )
将伪数组转换成数组
[].slice.call( 伪数组, 0 );
不传参 从 0 开始, [].slice.call( 伪数组 );
...,
toArray: function () { // 注意返回 dom 对象数组
// var res = [];
// for ( var i = 0; i < this.length; i++ ) {
// res.push( this[ i ] );
// }
// return res;
return slice.call( this );
},
...
添加 DOM 操作方法
appendTo 和 append
jepson.fn.extend({
appendTo: function ( selector ) {
var iObj = this.constructor( selector );
// 用构造函数构造出一个新对象,用以存储所有的 克隆体 和 本体,用以链式调用
var newObj = this.constructor();
for ( var i = 0; i < this.length; i++ ) {
for ( var j = 0; j < iObj.length; j++ ) {
// 只要不是最后一个,就克隆,最后一个就用本体
var temp = (j == iObj.length - 1) ? this[ i ] : this[ i ].cloneNode( true );
[].push.call( newObj, temp );
iObj[ j ].appendChild( temp );
}
}
return newObj;
},
append: function ( selector ) {
J( selector ).appendTo( this );
// // 给 当前对象 添加元素
// var iObj = this.constructor( selector ); // 要添加的元素
// for ( var i = 0; i < this.length; i++ ) { // 遍历当前对象
// for ( var j = 0; j < iObj.length; j++ ) { // 遍历要添加的元素
// // 只要不是最后一个要添加的 对象,就要clone要添加的元素
// var temp = (i == this.length - 1) ? iObj[ j ] : iObj[ j ].cloneNode( true );
// this[ i ].appendChild( temp );
// }
// }
return this;
}
});
prependTo
jquery 中 的 prepend 方法
<body>
<div class="c">
<div>111</div>
</div>
<div class="c">
<div>222</div>
</div>
</body>
<script src="../../../资料/jquery/jquery-1.12.0/jquery-1.12.0.js"></script>
<script>
var $1 = $( '<p>000</p>' );
var $2 = $1.prependTo( '.c' );
</script>
...,
prependTo: function( selector ) {
var iObj = this.constructor( selector );
var newObj = this.constructor();
for ( var i = 0; i < this.length; i++ ) {
for ( var j = 0; j < iObj.length; j++ ) {
var temp = ( j == iObj.length - 1 ) ? this[ i ] : this[ i ].cloneNode( true );
[].push.call( newObj, temp );
}
}
},
...
/* 扩展 DOM 静态方法 */
jepson.extend( {
prependChild: function ( parent, element ) {
// parent.insertBefore( 新元素, 旧元素 )
var first = parent.firstChild;
parent.insertBefore( element, first );
}
});