$element.remove(selector)
JQuery中大部分DOM操作API,都支持传递选择器对原集合进行过滤,不传则意味着全部
很多方法作为公共函数,会应用到不同的场景,其中还结合了构建JQuery的核心对象。在阅读源码的过程中可以针对指定场景简单的了解下,不要过分尝试解读,比如access、clearData、buildFragment、domManip等
1 detach和remove
两者都用于移除,detach不会移除元素上的事件和数据。通过JQuery绑定、存储的。
detach: function( selector ) {
return remove( this, selector, true );
},
remove: function( selector ) {
return remove( this, selector );
},
1.1 remove
function remove( elem, selector, keepData ) {
var node,
//根据selector对elem集合进行过滤,不建议将需要逻辑处理的赋值写在一个;号里,调试器在调试代码时,一步会走一个;号
nodes = selector ? jQuery.filter( selector, elem ) : elem,
i = 0;
for ( ; ( node = nodes[ i ] ) != null; i++ ) {
if ( !keepData && node.nodeType === 1 ) {
//getAll( node ) 获取node节点下的全部元素包括自身。
//jQuery.cleanData清除事件和数据
jQuery.cleanData( getAll( node ) );
}
if ( node.parentNode ) {
// jQuery.contains 当前document是否包含node
if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
//标记脚本已经执行过一次
setGlobalEval( getAll( node, "script" ) );
}
//移除元素
node.parentNode.removeChild( node );
}
}
return elem;
}
1.2 getAll函数的源码
function getAll( context, tag ) {
//content 是DOM元素 tag是标签的名字
// Support: IE <=9 - 11 only
// Use typeof to avoid zero-argument method invocation on host objects (#15151)
var ret;
if ( typeof context.getElementsByTagName !== "undefined" ) {
ret = context.getElementsByTagName( tag || "*" );
} else if ( typeof context.querySelectorAll !== "undefined" ) {
ret = context.querySelectorAll( tag || "*" );
} else {
ret = [];
}
//nodeName( context, tag ) context的节点名是否与tag相等,这个名字取得...
if ( tag === undefined || tag && nodeName( context, tag ) ) {
//将ret数组的内容放到[context]中
return jQuery.merge( [ context ], ret );
}
return ret;
}
tag || "*" 的执行逻辑是 从左到右执行,一个表达式可以转化为true时(Bollean(tag))时,返回这个表达式的结果,不再继续执行。
2 empty
empty: function() {
var elem,
i = 0;
for ( ; ( elem = this[ i ] ) != null; i++ ) {
if ( elem.nodeType === 1 ) {
//防止内存泄漏 清除绑定事件和数据
// Prevent memory leaks
jQuery.cleanData( getAll( elem, false ) );
//清除子节点
// Remove any remaining nodes
elem.textContent = "";
}
}
return this;
},
3 clone
clone: function( dataAndEvents, deepDataAndEvents ) {
//这里是非常值得提倡的地方,deepDataAndEvents默认是和dataAndEvents值一致,这符合大部分人对一个元素克隆行为的认知,而没有采取deepDataAndEvents不传默认就是false的写法!
dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
//jQuery.fn.map(this.map) => JQuery.map map可以理解为"映射",将数据逐一处理后,返回结果的集合。 jQuery.fn.map 将返回的结果传给了pushStack,用于记录框架操作过的DOM元素
return this.map( function() {
//在这里完成克隆
return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
} );
},
4 html
access作为"预处理"函数用在很多地方,比如对传进来的函数求值,以及处理多个dom元素的情况等。
在调试的过程中,如果我们不想进入这个函数中,可以在回调函数内部打一个断点,在按下F8,便可直接跳到新的断点处,再次调试时直接按F10就可以走到断点处
html: function( value ) {
return access( this, function( value ) {
var elem = this[ 0 ] || {},
i = 0,
l = this.length;
if ( value === undefined && elem.nodeType === 1 ) {
//获取值
return elem.innerHTML;
}
// See if we can take a shortcut and just use innerHTML
//rnoInnerhtml = <script|<style|<link/i
//rtagName = /<([a-z][^\/\0>\x20\t\r\n\f]+)/i 获取标签名
/*wrapMap 是对一些特殊元素进行包裹
比如td、option,td包裹上<table><tbody><tr></tr></tbody>
</table>
这里是可以防止的情况有,a.不生效 比如执行下列语句$(p)[0].innerHTML= "<td></td>" 不会报错也不会有效果,b.自动生成一些标签,
$("table"),innerHTML = "<td></td>" 会自动生成<tbody><tr></tr></tbody>
*/
if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
//对标html字符串进行一些预处理 比如<span/> 会成为<span></span>
value = jQuery.htmlPrefilter( value );
try {
for ( ; i < l; i++ ) {
elem = this[ i ] || {};
// Remove element nodes and prevent memory leaks
if ( elem.nodeType === 1 ) {
//清除绑定的事件和数据
jQuery.cleanData( getAll( elem, false ) );
//elem.innerHTML = ”div“是可以的
elem.innerHTML = value;
}
}
elem = 0;
// If using innerHTML throws an exception, use the fallback method
} catch ( e ) {}
}
if ( elem ) {
//不能通过innerHTML直接添加的通过一下方式添加 比如
//$("div.shadow").html($("<div>"))
this.empty().append( value );
}
}, null, value, arguments.length );
},
给大家推荐一款正则表达式的可视化工具
https://regexper.com/
网友评论