preface

Simple notes, nothing more ⚠️ ⚠️

Types of nodes

The node type

There are 12 node types. The nodeType can be obtained by nodeType and is expressed in numbers 1 to 12

  • NodeType: indicates the nodeType
  • NodeName, depending on the node type. For elements of type Element, nodeName equals the tag name
  • NodeValue, depending on the node type, is null for elements of type Element

Relationship between nodes

  • The childNodes property, which contains an array object of class NodeList. NodeList can be accessed directly using the brackets NodeList[0], nodelist.item (1). Array.from is converted to an Array object
  • The parentNode property points to the parentNode
  • PreviousSibling, the preceding sibling of the first is null,
  • NextSibling, the nextSibling, the nextSibling of the last is null,
  • FirstChild, the firstChild
  • LastChild, the lastChild
  • HasChildNodes (), returns true if there are child nodes

Manipulation of the node

  • Parentnode.appendchild () adds an element to the end of the childNodes list and returns the new element. If it is an existing element, the current node is moved.
  • Parentnode. iertBefore(insert node, reference node), if the reference node is null, the last node will be inserted. If the reference node is firstChild, the first node is entered.
  • Parentnode. replaceChild(Replace node, reference node)
  • Parentnode.removechild (Deleted node)
  • CloneNode (Boolean), Boolean passing false copies only the current node, Boolean passing true copies the current node and its children. CloneNode does not copy properties added by JS, such as event handlers.
  • Normalize: Normalizes text nodes

The Document type

Document object Document is an instance of HTMLDocument (HTMLDocument inherits Document), representing the entire HTML page. Document is an attribute of the Window object and is therefore a global object. The nodeType of Document is 9

Document child node

  • Document.documentelement, which returns an HTML element

  • Document.childnodes [0], which returns an HTML element

  • Body property, which returns the body element

  • Doctype property, return

  • Title, the text that contains the label

  • URL, the complete URL of the current page

  • Domain, the domain name of the current page, can be changed, but only once

  • Referrer, the source of the page

💡 document.domain can be modified, but the modification is limited. For example, www.baidu.com can be modified to image.baidu.com.

💡 When a page nested with an iframe, you can modify the domain properties of the iframe, and when two documents have the same domain properties, you can share javascript objects.

Positioning elements

  • getElementById
  • GetElementsByTagName, which returns an HTMLCollection array object
    • HTMLCollection object namedItem method, can be specified according to the node name, the element
    • Document. GetElementsByTagName (‘ * ‘), will return all elements
  • GetElementsByName, gets the element with the specified name
  • Document. images, which gets all the image elements
  • Document.links gets all the A tags that have the href attribute
  • Document. forms, which gets all the form elements

const images = document.getElementsByTagName('img')
// Get the image whose name is t1
images.namedItem('t1')
Copy the code

Document writing

  • Write: writes text
  • Writeln, writes text and wraps
  • Open, open a webpage
  • Close, close the page

write

  1. Write If executed after OLOad, the write method overwrites the entire page.
  2. Write If executed after oload, the write method is written after the current script. The write in writingscriptAfter the tag,

Element type

NodeType of Element is 1, nodeName is the label name, and nodeValue is null.

NodeName and tagName return the same value, but tagName usually returns the upper case of the tagName

HTML

All HTML elements are of type HTMLElement, which inherits from the Element type and adds some attributes of its own.

Common attributes:

  • id
  • Title, additional information
  • Dir, writing direction
  • className

Attribute method

  • GetAttribute: Gets the attribute. The attribute name is case insensitive, and ID is the same as ID.
  • SetAttribute (key, value) : Sets the attribute. The attribute name is automatically lowercase
  • RemoveAttribute, remove the attribute, not just the value. Deletes key and value

The attributes property

The Attributes attribute contains a NamedNodeMap instance, where each attribute of an element is stored.

  • GetNamedItem (name) returns the node in the NamedNodeMap instance whose attribute is name
  • RemoveNamedItem (name) removes the object whose attribute is name
  • SetNamedItem (node) sets the attribute node
// id1 is the same as id2
const id1 = element.attributes.getNamedItem("id").nodeValue;
const id2 = element.attributes["id"].nodeValue;

// Delete attributes
element.attributes.removeNamedItem("id")

// Set the properties
const node = document.createAttribute("class");
node.value = "democlass";
element.attributes.setNamedItem(node);
// You can modify the property value directly
element.attributes["id"].nodeValue = "someOtherId";
Copy the code

Create the element

  • Document.createelement () creates the element

The Text type

NodeType = 3, nodeValue = text, nodeName = #text, no child nodes are supported. ParentNode is the Element object. Once a reference to a text node is obtained, it can be modified directly via nodeValue


const textNode = document.getElementsByClassName('color_h1') [0]
textNode.firstChild.nodeValue = 'Hello'
// Or modify the data property to have the same effect as the nodeValue
textNode.firstChild.data = 'Hello'
Copy the code

Creating a text node

  • document.createTextNode()
let element = document.createElement("div");
element.className = "message";
 
// Create a text node and insert it into the element
let textNode1 = document.createTextNode("Hello");
element.appendChild(textNode1);

// Multiple text nodes can be inserted
let textNode2 = document.createTextNode("World!");
element.appendChild(textNode2);

document.body.appendChild(element);
Copy the code

Normalized text node

Calling the Normalize method on an element containing multiple text nodes merges the text nodes into a single text node

let element = document.createElement("div");
element.className = "message";
 
// Create a text node and insert it into the element
let textNode1 = document.createTextNode("Hello");
element.appendChild(textNode1);

// Multiple text nodes can be inserted
let textNode2 = document.createTextNode("World!");
element.appendChild(textNode2);

// Text nodes will be merged
element.normalize()
Copy the code

The Comment type

Comment nodeType, nodeType is 8, nodeValue is the comment content, nodeName value is #comment”, parentNode is Document or Element and child nodes are not supported

// <div id="test"><! - comments -- > < / div >
let element = document.getElementById("test");
// Comment the node
let comment = div.firstChild;
// Comment out the contents of the node
console.log(comment.data)
console.log(comment.nodeValue)
Copy the code

Creating a comment node

  • document.createComment()

CDATASection type

NodeType = 4.

DocumentType type

NodeType is equal to 10, which does not support dynamic creation. ParentNode is equal to the Docuemtn object, and DocumentType can be obtained using Document.docType.

  • Name, the document type name,<! DOCTYPEThe rest
<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // html
        console.log(document.doctype.name)
    </script>
</body>
</html>
Copy the code

DocumentFragment type

DocumentFragment, nodeType = 11. DocumentFragment can be understood as a repository. DocumentFragment stores all nodes to be added to the document

Creating a document fragment

  • document.createDocumentFragment

use

// If you do not use the document fragment, the browser will render 3 times
let ul = document.getElementById("myList");
for (let i = 0; i < 3; ++i) {
    let li = document.createElement("li");
    li.appendChild(document.createTextNode(`Item ${i + 1}`));
    ul.appendChild(fragment);
}

// After using a document fragment, the browser will render it only once
let fragment = document.createDocumentFragment();
let ul = document.getElementById("myList");
for (let i = 0; i < 3; ++i) {
    let li = document.createElement("li");
    li.appendChild(document.createTextNode(`Item ${i + 1}`));
    fragment.appendChild(li);
}
ul.appendChild(fragment);
Copy the code

Attr type

The Attr node resides on the attributes attribute of the element. NodeType is equal to 2, nodeName is equal to the attribute name, and nodeValue is equal to the attribute value. The Attr type is a node but not part of the DOM tree

// The name of attr is align
let attr = document.createAttribute("align");
// The value of attr is left
attr.value = "left";
// Set attributes for the element
element.setAttributeNode(attr);
Copy the code

DOM programming

Dynamic script

Dynamically inserted inline scripts are not executed if the script is inserted with innerHTML. Nodes can only be inserted through apis like appendChild, DOM, etc.

const script = document.createElement("script"); 
script.type = "text/javascript";

script.appendChild(document.createTextNode(code));


// Can be executed
document.body.appendChild(script)
// Script cannot be executed
document.body.innerHTML = script
Copy the code

Dynamic style


function loadStyleString(css){
    let style = document.createElement("style");
    style.type = "text/css";
    style.appendChild(document.createTextNode(css));
    let head = document.getElementsByTagName("head") [0];
    head.appendChild(style);
}
Copy the code

NodeList

NodeList is similar to HTMLCollection, but HTMLCollection objects have an additional namedItem method that can be referenced by the element’s name

MutationObserver

MutationObserver, which allows you to view an entire document, or a part of the DOM, or an element. Callback is triggered asynchronously when changes occur

The basic use

// Mo does not associate any DOM objects. Instead, it needs to use an observer
// Associate specific DOM objects with properties that already need to be observed
const mo = new MutationObserver(() = > {
    console.log('dom change')})// Observe changes to the document.body element and attributes. When the body property changes, the callback in MutationObserver is triggered
// But a change in the document.body child, or in other docuemnt.body contents, does not trigger callback,
mo.observer(document.body, {
    attributes: true
})
Copy the code

MutationRecord array

The MutationRecord array records a set of information that a callback might have been triggered by more than one operation. Each message contains what changes have taken place, what elements have been affected, etc.

const div = document.getElementById('id1');
const mo = new MutationObserver((MRecord) = > {
    // Print the following result
    console.log(MRecord);
});
mo.observe(div, {
    attributes: true}); div.dataset.name ='World! ';
Copy the code

Multiple changes to the MutationRecord array will have multiple contents


const div = document.getElementById('id1');
const mo = new MutationObserver((MRecord) = > {
    console.log(MRecord);
});
mo.observe(div, {
    attributes: true}); div.dataset.name ='World! ';
div.dataset.name = 'Hello World! ';
Copy the code

callback

The first argument to callback is an array of MutationRecord and the second argument is an instance of MutationObserver

Disconnect method

Calling the Disconnect method stops listening for the callback.

// Stop listening for callbacks
mo.disconnect()
Copy the code

MutationObserver reuse

Call the observe method multiple times to observe multiple nodes.


const div1 = document.getElementById('id1');
const div2 = document.getElementById('id2');
const mo = new MutationObserver((MRecord) = > {
    console.log(MRecord);
});
mo.observe(div1, {
    attributes: true}); mo.observe(div2, {attributes: true}); div1.dataset.name ='1';
div2.dataset.name = '2';
Copy the code

MutationObserver reuse

Calling Disconnect does not terminate the MutationObserver instance, we can re-invoke Observe and continue to use it


const div1 = document.getElementById('id1');
const div2 = document.getElementById('id2');
const mo = new MutationObserver((MRecord) = > {
    // The MRecord array has only one content
    console.log(MRecord);
});
mo.observe(div1, {
    attributes: true}); div1.dataset.name ='1';
mo.disconnect();
mo.observe(div2, {
    attributes: true}); div2.dataset.name ='2';
Copy the code

MutationObserverInit with observation scope

MutationObserver can observe changes in attributes, changes in child nodes, and changes in text

  • Subtree, Boolean, whether to observe children
  • Attributes, Boolean, whether to view attributes
  • AttributeFilter, string[], looks specifically at changes in those attributes
  • AttributeOldValue, Boolean, whether the previous attribute value is recorded in the MutationRecord array.
  • CharacterData, Boolean, whether to observe changes to modify characterData (text node, comment node)
  • CharacterDataOldValue, Boolean, Whether the previous character value is recorded in the MutationRecord array.
  • ChildList, Boolean, changes whether child nodes trigger observation

Subtree, set to true, observes the entire subnumber. If you remove the offspring from the subtree, if you modify it outside the original subtree, it still triggers the change.

ChildList, set to true, looks only at first-level subtrees

Asynchronous callback and record queue

Each change is recorded in the MutationRecord instance and added to the record queue, which is unique to each MutationObserver instance. Each time a MutationRecord is added to the queue, the previously registered callback is triggered if the current microtask queue length is 0.

takeRecords

Empty the queue and return the contents of the queue. It also stops callback listening


// Console is not triggered
let observer = new MutationObserver((mutationRecords) = > console.log(mutationRecords));

observer.observe(document.body, { attributes: true });

document.body.className = 'foo';
document.body.className = 'bar';
document.body.className = 'baz';
// [MutationRecord, MutationRecord, MutationRecord]
console.log(observer.takeRecords());
/ / []
console.log(observer.takeRecords());
Copy the code

Performance, memory, and garbage collection

The MutationObserver is a weak reference to the target DOM. If the target node is garbage collected, the MutationObserver does not block the collection.

The target node is a strong reference to the MutationObserver, and if the target node is reclaimed, the MutationObserver is reclaimed as well.

The MutationRecord instance prevents the node from being garbage collected. You can extract useful information from a MutationRecord, save it to a new object, and finally discard the MutationRecord.

reference

  • Mutation Observers—subtree