Advanced JavaScript programming for reading notes 4th Edition (Chapter 14)

Time:2021-2-27

preface

Simple notes, nothing else

Type of node

Node type

There are 12 types of nodes. The node type is obtained by nodeType and represented by numbers 1-12

  • NodeType, the type of the node
  • NodeName, depending on the type of node. For elements of element type, nodeName is equal to the tag name
  • NodeValue depends on the type of the node. For elements of element type, nodeValue equals null

Node relationship

  • The childNodes property contains the array object of the NodeList class. NodeList can directly use the bracket NodeList [0], NodeList.item (1) To access the elements. Array.from Convert to array object
  • Parentnode property, pointing to the parent node
  • Previoussibling, the previous sibling node, the first sibling node is null,
  • Nextsibling, the next sibling node, and the last sibling node is null,
  • Firstchild, the first child node
  • Lastchild, the last child node
  • Haschildnodes(), returns true if there are child nodes

Manipulation node

  • parentNode.appendChild (), add an element at the end of the childNodes list, and return a new element. If it is an existing element, the current node will be moved.
  • parentNode.iertBefore If the reference node is null, it will be inserted to the last node. If the reference node is firstchild, the first node is involved.
  • parentNode.replaceChild (replacement node, reference node)
  • parentNode.removeChild (deleted nodes)
  • CloneNode (Boolean). If Boolean passes false, only the current node will be copied. If true, the current node and its children will be copied. CloneNode will not copy the attributes added by JS, such as event handler.
  • Normalize, normalize text nodes

Document type

The document object document is an instance of htmldocument (htmldocument inherits document) and represents the entire HTML page. Document is a property of the window object, so it is a global object. The nodeType type of document is equal to 9

Document child node

  • document.documentElement To return the HTML element
  • document.childNodes [0], return the HTML element
  • The body attribute returns the body element
  • DOCTYPE property, return <! DOCTYPE HTML > to
  • Title, the text containing the < title > tag
  • URL, the complete URL of the current page
  • Domain, the domain name of the current page, can be modified, but only once
  • Referrer, the source of the page

document.domain , can be modified, but there are some limitations, such as www.baidu.com , can be modified to image.baidu.com .

When an iframe is nested in a page, the domain property of iframe can be modified. When the domain property of two documents is the same, JavaScript objects can be shared.

Positioning elements

  • getElementById
  • GetElementsByTagName, returns the htmlcollection class array object

    • The nameditem method of htmlcollection object can obtain elements according to the specified node name
    • document.getElementsByTagName (‘*’), all elements will be returned
  • Getelementsbyname, get the element of the specified name
  • document.images To get all the picture elements
  • document.links To get all the a tags that contain the attribute
  • document.forms To get all the form elements
const images = document.getElementsByTagName('img')
//Get the image with the name attribute T1
images.namedItem('t1')

Document writing

  • Write, write text
  • Writeln, write text and wrap
  • Open, open the web page
  • Close, close the web page

write

  1. If write occurs after oload, the write method rewrites the entire page.
  2. If write is executed before oload, the write method will be written after the current script. Write is writingscriptWhen it comes to labeling,

Element type

NodeType of element type equals 1, nodeName equals tag name, nodeValue equals null

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

HTML

All HTML elements are of HtmlElement type. HtmlElement type inherits from element type and adds some attributes of its own.

Common attributes:

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

Attribute method

  • Getattribute, get the attribute. The attribute name is not case sensitive, and ID is equal to ID.
  • SetAttribute (key, value), set the attribute, and the attribute name will be normalized to lowercase automatically
  • Removeattribute, delete attribute, not just delete value. Key and value will be deleted

Attributes attribute

The attributes attribute contains a NamedNodeMap instance, and each attribute of the element is saved in the NamedNodeMap instance.

  • Getnameditem (name), returns the node in the NamedNodeMap instance whose attribute is equal to name
  • Remove nameditem (name), delete the node whose attribute is equal to name
  • Setnameditem (node) to set the attribute node
//Id1 and Id2 are equivalent
const id1 = element.attributes.getNamedItem("id").nodeValue;
const id2 = element.attributes["id"].nodeValue;

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

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

Create element

  • document.createElement (), create element

Text type

NodeType is equal to 3, nodeValue is equal to text content, nodeName is equal to # text, and child nodes are not supported. Parentnode is an element object. After obtaining the reference of the text node, you can modify it directly through nodeValue

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

Create 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);

//You can insert multiple text nodes
let textNode2 = document.createTextNode("World!");
element.appendChild(textNode2);

document.body.appendChild(element);

Normalize text nodes

Calling the normalize method on an element that contains 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);

//You can insert multiple text nodes
let textNode2 = document.createTextNode("World!");
element.appendChild(textNode2);

//Text nodes will be merged
element.normalize()

Comment type

Comment node type, nodeType is 8, nodeValue is the content of the comment, nodeName is # comment “, parentnode is document or element, and child node is not supported

//< div id = "test" > <! -- comment -- > < / div >
let element = document.getElementById("test");
//Annotation node
let comment = div.firstChild;
//Annotation node的内容
console.log(comment.data)
console.log(comment.nodeValue)

Create annotation node

  • document.createComment()

CDATASection type

NodeType equals 4, other contents are omitted

DocumentType type

NodeType is equal to 10. Dynamic creation is not supported. Parentnode is equal to docuemtn object. You can use document.doctype Gets the DocumentType object.

  • Name, the name of the document type,<!DOCTYPEWhat follows
<!DOCTYPE html>
<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>

Documentfragment type

The nodeType of a document fragment is equal to 11. A document fragment can be understood as a warehouse in which all the nodes to be added to the document are stored

Create a document fragment

  • document.createDocumentFragment

use

//If you don't use a document clip, the browser renders three 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 clip, the browser will render 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);

Attr type

The attributer node exists in 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. Although the attributer type is a node, it is not a part of the DOM tree

//The name of attr node is align
let attr = document.createAttribute("align");
//The value of attr node is left
attr.value = "left";
//Setting properties for an element
element.setAttributeNode(attr);

DOM programming

Dynamic script

For dynamically inserted inline script, if the script is inserted with innerHTML, it will not be executed. You can only insert nodes through the DOM API such as appendChild.

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

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);
}

NodeList

NodeList is similar to htmlcollection, but the htmlcollection object has an additional nameditem method, which can get the reference through the name of the element

MutationObserver

Mutationobserver can observe the whole document, or a part of the DOM, or an element. When a change occurs, a callback is triggered asynchronously

Basic use

//Mo does not associate any DOM objects, but uses observer
//Associate specific DOM objects with attributes that need to be observed
const mo = new MutationObserver(() => {
    console.log('dom change')
})
//Observation document.body Element, attribute change. When the properties of the body change, the callback in the mutationobserver will be triggered
//But document.body Changes in offspring, or docuemnt.body Other content changes will not trigger a callback, 
mo.observer(document.body, {
    attributes: true
})

Mutationrecord array

The mutationrecord array records a set of information that the trigger of a callback may be caused by multiple operations. Each information contains the changes that have taken place, the elements that have been affected, etc.

const div = document.getElementById('id1');
const mo = new MutationObserver((MRecord) => {
    //The print results are as follows
    console.log(MRecord);
});
mo.observe(div, {
    attributes: true,
});
div.dataset.name = 'World!';

Advanced JavaScript programming for reading notes 4th Edition (Chapter 14)

If you modify the mutationrecord array many times, there will be 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!';

Advanced JavaScript programming for reading notes 4th Edition (Chapter 14)

callback

The first parameter of callback is the array of mutationrecord, and the second parameter is the instance of mutationobserver

Disconnect method

Calling the disconnect method stops listening for callbacks.

//Stop listening for callbacks
mo.disconnect()

Mutationobserver reuse

By calling the observe method many times, you can 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';

Advanced JavaScript programming for reading notes 4th Edition (Chapter 14)

Reuse of mutationobserver

Calling disconnect does not terminate the life of the mutationobserver instance. We can call observe again and continue to use it

const div1 = document.getElementById('id1');
const div2 = document.getElementById('id2');
const mo = new MutationObserver((MRecord) => {
    //The mrrecord 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';

Mutationobserverinit and observation range

Mutationobserver can observe the changes of attributes, child nodes and text

  • Subtree, Boolean, observe offspring
  • Attributes, Boolean, observe attributes
  • Attributefilter, string [] to observe the changes of those attributes
  • Attributeoldvalue, Boolean, whether to record the previous attribute value in the mutationrecord array.
  • Characterdata, Boolean, whether to observe the change of modified character data (text node, comment node)
  • Characterdataoldvalue, Boolean, whether to record the previous character value in the mutationrecord array.
  • Child list, Boolean, modify whether the child node triggers observation

Subtree, set to true, and observe the whole subtree. If a descendant is removed from the original subtree and modified, the change will still be triggered.

Childlist, set to true, only observe one level subtree

Asynchronous callback and record queue

Each change information will be recorded in the mutationrecord instance, and then added to the record queue, which is unique to each mutationobserver instance. Each time the mutationrecord is added to the queue, if the length of the current micro task queue is 0, the previously registered callback will be triggered.

takeRecords

Clears the queue and returns the contents of the queue. At the same time, the callback listening will stop

//The console will not be 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());

Performance, memory and garbage collection

Mutationobserver is a weak reference to the target dom. If the target node is garbage collected, the mutationobserver will not hinder the collection.

The target node is a strong reference to mutationobserver. If the target node is recycled, mutationobserver will also be recycled.

The mutationrecord instance prevents the node from being garbage collected. Useful information of mutationrecord can be extracted and saved to a new object.

reference resources