This section talks about the Delete Elements module in the DOM operation module, which is used to delete a node in the DOM or to uninstall the node from the DOM tree. If the node has binding events, we can choose to keep or delete them. There are three interfaces for deleting elements:
- empty(); Remove all child elements of the matching element.Remove data and events associated with all descendant elements to avoid memory leaks.Then remove the child elements.(
- remove(selector,keepData); remove the selector element from the matching element.; selector is an optional selector expression that is removed if not passed in, or only the corresponding matching elements are removed.KeepData is optional, indicating whether matching elements and the data and events associated with their descendant elements are retained
- detach(selector); remove the set of matching elements from the document; but retain the data and events associated with descendant and matching elements, often used in scenes where removed elements are later inserted into the document again.
To put it directly,
- empty() directly removes the currently matching element
- remove() will save the element in the matching parameter 1 selector of the currently matched element, if parameter 2 keepData is true then save the event for the DOM node, otherwise remove the event
- detach() is implemented by calling remove() to remove the currently matching element, but retains the data, which is implemented by calling remove(selector,true)
writer by:Desert QQ:22969969
Lift a chestnut:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script> </head> <body> <div> <h1>Hello</h1> </div> <p>Friend</p> <button id="b1">Test 1</button> <button id="b2">Test 2</button> <button id="b3">Test 3</button> <script> $('h1').click(function(){console.log('h1 click')}); //to h1 Element adds a click event $('p').click(function(){console.log('p click')}); //to P Element adds a click event //All three buttons below will implement the h1,p Elements from DOM Remove and Insert from Tree body Before the child node, the difference is that the output information is different when the child node is clicked b1.onclick=function(){$('h1,p').remove().prependTo('body')} //After clicking the Test 1 button h1 and p Elements moved to body The top of the child nodes,But click again h1 and p None of the elements react b2.onclick=function(){$('h1,p').remove('p').prependTo('body')} //After clicking the Test 1 button h1 and p Elements moved to body The top of the child nodes,click h1 Output, Click p No output b3.onclick=function(){$('h1,p').detach().prependTo('body')} //After clicking the Test 1 button h1 and p Elements moved to body The top of the child nodes,click h1 and p Has Output </script> </body> </html>
Render as follows:
The corresponding DOM tree is as follows:
We bind an event to the h1 and p elements, click output: h1 click and p click, click output as follows:
In addition, whether you click Test 1, Test 2, or Test 3, the H 1 and p elements are uninstalled from the DOM tree and inserted at the top of the body subnode, as follows:
Clicking on the h1 and p elements will produce different outputs:
- For the Test 1 button; click on H 1 and p without any output; all matching element events are deleted because the remove() method is called and no parameters are passed
- For the Test 2 button; there is output by tapping h1 and no output by tapping p; since P was passed when the remove() method was called, events for the P element were deleted, and events for the h1 element were not deleted
- For the Test 2 button; there is no output by clicking on h1 and p; because the detach() method is called, all elements'data is preserved, which is achieved by calling remove (selector, true) inside detach(), i.e. the remove parameter 2 is true
Source Code Analysis
Before explaining empty(), remove(), and detach(), introduce a jQuery API, namely $.cleanData(elems), whose parameters are a collection of DOM nodes (which can be the return value of document.getElementsByTagName), which is used to remove a jQuery event bound to a DOM node. Let's move a chestnut:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script> </head> <body> <p>Hello World</p> <button>test</button> <script> $('p').click(function(){console.log('p click')}); //to P Element adds a click event $('button').click(function(){ $.cleanData(document.getElementsByTagName('p')) //to button Button adds a button Events, internal calls $.cleanData Go clear p Events bound on elements }) </script> </body> </html>
Render as follows:
When initializing, we click the Hello World console to output information. If we click the button and then click Hello World, we will not output it because $.cleanData uninstalls events for this DOM element, $.cleanData implements the following:
jQuery.extend({ cleanData: function( elems ) { //Remove Multiple DOM All data and events of the element, elems Is to remove data and events DOM Array of elements. var data, id, cache = jQuery.cache, special = jQuery.event.special, deleteExpando = jQuery.support.deleteExpando; for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { //Traverse through each matching element if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { //If setting attributes is not supported, skip this cycle. jQuery.noData Is an array that holds node names that do not support extended properties. continue; } id = elem[ jQuery.expando ]; //Property Name,Note 1 if ( id ) { //If the DOM Objects have jQuery.expando Property means data has been set. data = cache[ id ]; if ( data && data.events ) { //If DOM The associated data cache object exists and contains events Attribute, described in DOM Up-bound event, remove for ( var type in data.events ) { //data.events yes DOM Element's event cache object, stored DOM All events of the element if ( special[ type ] ) { jQuery.event.remove( elem, type ); // This is a shortcut to avoid jQuery.event.remove's overhead } else { jQuery.removeEvent( elem, type, data.handle ); } } // Null the DOM reference to avoid IE6/7/8 leak (#7054) if ( data.handle ) { data.handle.elem = null; } } if ( deleteExpando ) { //If jQuery.support.deleteExpando;Return ture,That is, the browser supports deletion DOM Extended attributes on elements delete elem[ jQuery.expando ]; //delete DOM Elemental jQuery.expando attribute } else if ( elem.removeAttribute ) { //If the browser does not support deletion DOM Extended attributes on elements are called removeAttribute Delete Properties elem.removeAttribute( jQuery.expando ); } delete cache[ id ]; //delete DOM Element's Data Cache Object cache[id] } } } /*slightly*/ })
Note 1: The information for events bound by jQuery exists in $.cache, and the key name is jQuery.expando for DOM objects, which is elem [jQuery.expando]. If you have questions, you can see the explanation of the previous events: https://www.cnblogs.com/greatdesert/p/11679334.html
CleaData is the event of deleting all DOM elements in the parameter elems. Both empty() and remove() are implemented based on cleanData, and empty() is implemented as follows:
jQuery.fn.extend({ empty: function() { //Remove all child elements of the matching element from the document. for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { //Traverse through each element that currently matches // Remove element nodes and prevent memory leaks if ( elem.nodeType === 1 ) { jQuery.cleanData( elem.getElementsByTagName("*") ); ////Remove data and events associated with all descendant elements first to avoid memory leaks } // Remove any remaining nodes while ( elem.firstChild ) { //Then remove the child elements. elem.removeChild( elem.firstChild ); } } return this; }, })
CleaData () is called inside empty() to remove data and events from all descendant nodes, and then each DOM node is uninstalled through a while() loop, which is a good understanding. For remove(), the following are implemented:
jQuery.fn.extend({ remove: function( selector, keepData ) { //Remove from Matching Elements selector Element, which traverses the set of matching elements, deletes data and events for descendant and matching elements to avoid memory leaks, and then removes matching elements. for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { //Traverse current matching elements if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { //If no incoming selector Parameter, or passed in selector Parameter, and the current element matches it if ( !keepData && elem.nodeType === 1 ) { //If no incoming keepData Parameter and elem Is Element Node jQuery.cleanData( elem.getElementsByTagName("*") ); //Remove all data and events from descendant elements jQuery.cleanData( [ elem ] ); //Remove element nodes. } if ( elem.parentNode ) { //Call Native Method removeChild()Remove nodes. elem.parentNode.removeChild( elem ); } } } return this; }, detach: function( selector ) { return this.remove( selector, true ); //call remove()To achieve this, parameter 2 is passed in true }, })
The remove() method selects the matching element based on the selector and unloads it from the DOM tree. If a keepData is passed in, the data is saved, otherwise the data is deleted. For detach, this is done by calling remove().