This section talks a little bit about the basics of DOM

Fragmented content: fetching elements, element prototype chains, nodeTypes, add, delete, change, DOM cross-threading — slow? , the life cycle of the TAB insertion page

Front knowledge

What knowledge is needed

  • Understand simple JS syntax such as variables, if else, loops
  • Can recite seven JS data types (four bases, two empty objects, one object, bigInt)
  • Can recite five falsy values of JS (0, NaN, null, undefined, empty string)
  • Know that functions are objects and arrays are objects
  • Div and SPAN tags are used
  • Simple CSS layout (Flex)

A web page is a tree

The first point

Let me draw it as a tree.

How does JS manipulate this tree

  • JS can only operate JS, is not the operation of the web page
  • The browser provides the ability to add a Document to the window
  • As long as you have the document object, JS can manipulate the tree

The sample

Open any website with Chrome on the console type:window.document gets a #documentThe mouse on the`#document`You will see that the entire page is selecteddocumentContains the entire pageCopy the code

Document to get the root node of the page

  • The root node has head, body…

JS uses Document to manipulate web pages

This is the Document Object Model

  • The idea of using a Document Object to manipulate the entire web page is called the Document Object Model.

  • Hereinafter referred to as the DOM

The DOM is difficult to use

Please keep this fact in mind

  • I said before, “JS is not good in its originality, and good in its originality.”
  • DOM can be even harder to use than JS
  • “Nobody wants to use the DOM”

I’ll figure out a way to solve this problem

If you think DOM is retarded

Don’t doubt yourself. What you think is right

  • DOM’s interface design is very anti-human
  • The front end has to use jQuery to manipulate the DOM
  • Later, jQuery was replaced by Vue, so most people use Vue to manipulate the DOM
  • React was used to manipulate the DOM
  • Never use the DOM’s native functionality to manipulate the DOM. Native functionality is very anti-human

Pictures from

Gets the element’s API

Get elements, also known as tags

What is an API – It is not defined exactly, but you will know what an API is after listening to it

There are a lot of API

By id

windowId name id namedocument.getElementById('id name')
Copy the code

For example, 👇

<input id="kw">
Copy the code
window.kw                     // 
kw                            // <input id="kw">
document.getElementById('kw') // 
Copy the code

Special case 👇

When the id is JS keyword/attribute, the element cannot be retrieved using the previous two simple methods

// As shown below
window.parent                      // The parent window is the parent window
document.getElementById('parent')  // This is the only way to write it
Copy the code

Therefore, as long as the ID does not conflict with the global attribute, it is easiest to use the ID directly

If you accidentally collide, the next best thing is to use this very long API

By tag name

/* * Find all elements with tag names of div. To get a specific div, use the subscript (also iterated) */
document.getElementsByTagName('div') [0]   
Copy the code

Get elements by class

/* * Find all elements whose class is red. To get a specific red element, use the subscript (also iterated) */
document.getElementsByClassName('red') [0]
Copy the code

The latest API: Query

Query is not a jQuery API, but is native to JS

QuerySelector and getElement(s)ByXxx methods

QuerySelector (), which takes a CSS selector and returns the first element that matches the pattern

QuerySelectorAll (), which selects all matched elements

document.querySelector('# id name')    // Using CSS syntax, CSS can find this tag in parentheses
document.querySelectorAll('.red') [0]
Copy the code

Which to use ⭕️

  • The latest at work, querySelector and querySelectorAll
  • Do demo direct use IDXXX, do not let people found
  • Use getElement(s)ByXxx for compatibility with IE deplorables

Gets the API for a particular element

Getting HTML elements

document.documentElement
Copy the code

Get the head element

document.head
Copy the code

Get the body element

document.body
Copy the code

Get Windows (Windows are not elements)

window
Copy the code

Get all elements

document.all
Copy the code
  • This document.all is weird, the sixth falsy value

What is the element that you get

It’s obviously an object, and we need to figure out its prototype

Grab a div object and look at it

let div = document.getElementsByTagName('div') [0]   // www.baidu.com
console.dir(div)  
// Use dir to print structures. (As shown below, there are many attributes added by constructors.)
// Focus on [prototype chain]
Copy the code

Note: HTMLDivElment written here is not a real prototype

div.__proto__ === HTMLDivElment            // false
div.__proto__ === HTMLDivElment.prototype  // true   
Copy the code
// JS classic formulaObject.__proto__ === its constructor. PrototypeCopy the code

Console. dir(div) starts looking at the prototype chain

  1. Open the outermost div#wrapper.wrapper_new, and the first thing you see is the attributes of the div itself

  2. HTMLDivElement. Prototype

    • If I click open, there are a lot of attributes in there, that are common to all divs, so don’t look at them
  3. HTMLElement. Prototype

    • There are attributes common to all HTML tags, so don’t bother looking
  4. Element. Prototype

    • These are common attributes for all XML and HTML tags, so you wouldn’t think that browsers could only display HTML
    • The X for AJAX is XML. Before JSON was invented, it was all XML (XML also has tags in it)
    • This includes XML, HTML, SVG,… Different tags have attributes in common, hence the name Element
    • On top of Element, we have the node property of 👇
  5. The fourth layer is Node. Prototype

    • Inside these are attributes common to all nodes, including XML tag text comments, HTML tag text comments, and so on
  6. EventTarget. Prototype

    • There are only three common attributes: addEventListener, dispatchEvent, and removeEventListener
    • The most important function attribute is addEventListener
  7. The final layer of prototypes is Object.prototype (root Object)

    • And then it’s null

In summary, div is a very complex object

Div complete prototype chain

Own properties and common properties, click to view

let div = document.querySelectorAll('.red') [0]
Copy the code
  • The div is constructed with HTMLDivElement
  • The HTMLDivElement constructor adds attributes to this (this refers to div)
  • Div also inherits from Element, so Element also adds attributes to this
  • It also inherits the Node constructor and adds some properties
  • So each layer of constructor adds attributes to the div

Example 👇

requestFullScreen()   // Request full screen (common to all elements)
Copy the code

head.requestFullScreen() // Full screen display of head elements // This API is generally not very compatible and is usually not used
// Each element can be as big as the screen
// Head can call this API because it inherits from the prototype chain
Copy the code

conclusion

  • So we know exactly what div we’re getting
  • It’s an object with six levels of prototypes

NodeType nodeType

Nodes? Element? Stupid can’t tell the difference

In a web page, there are many types of nodes. The most common are elements, also known as tags

Nodes Nodes include the following types

  • 1 represents the Element Element, also known as Tag (most commonly)
  • 3 indicates Text
  • 8 indicates comments
  • 9 indicates the Document
  • 11 indicates the DocumentFragment

(Remember 1 and 3)

The MDN is fully described, with x. nodetype giving a number

// The type of any element can be obtained by using.nodeType
div.nodeType  // 1 indicates a label
Copy the code

The sample

// www.baidu.com
let div = document.getElementsByTagName('div') [0]
div.nodeType  / / 1
div.childNodes  // Look at all the children of div // get the Nodelist(5) pseudo-array. 0: text The first child node is text
div.firstChild  // #text get the text node
div.firstChild.textContext  Get the contents of the text "" is a space
div.firstChild.nodeType  // the node type of the first child of the div is 3 text
Copy the code

Add, delete, change and check nodes

The programmer’s destiny is to add, delete, change and check

  • At the back end, add, delete, change and check the [database]
  • Front end, add, delete, change and check the [page elements]

increase

Create a label node

let div1 = document.createElement('div') 
// "DOM anti-human" is verified again: create an element that writes such a long word
document.createElement('style') 
document.createElement('script') 
document.createElement('li')
/ / < div > < / div >, < style > < / style >, < script > < / script >, < li > < / li >
Copy the code

Create a text node

text1 = document.createTextNode('hello')Text1 =' hello '
// Because 'hello' is a string; A text node is an object (containing many prototypes, functions, etc.)
Copy the code

Insert text inside the tag

Two forms, three ways to write it

div1.appendChild(text1) 
div1.innerText = 'hello'Or div1. TextContent ='hello'
Div1.appendchild (' hello ')
Copy the code
  • AppendChild is added by the Node constructor
  • TextContent is also added by the Node constructor
  • The innerText is added by the HTMLElement constructor

Use the interface provided by Node if you like

If you like HTMLElement use the interface provided by HTMLElement

  • But you can’t mix them
  • AppendChild can receive only one Node

To sum up

<div>hello</div>
Copy the code
// Create the HTML tag 👆 using DOM
// The following three lines of code are required to implement
let div1 = document.createElement('div')
let text1 = document.createTextNode('hello') div1. The appendChild (text1)Copy the code

Div1 will not be displayed on the page, but will live in JS memory until inserted into the page.

Insert into the page

  • The label created by default is in the JS thread
    • Does not show up on the page, just lives in JS memory
  • You have to insert it into head or body for it to work and show up on the page
    • Create a style or link element… It needs to be passed into the head for it to work
  • AppendChild inserts elements at the end of the target container
document.body.appendChild(div) 
document.head.appendChild(div)
/ / orElement already in the page. AppendChild (div)Copy the code

case

let div1 = document.createElement('div')  // Create a div element
let text1 = document.createTextNode('hello')// Create a text node
div1.appendChild(text1)  AppendChild adds a text node to the div element. At this point, the div is still in memory and not displayed on the page
document.body.appendChild(div1) // 
      
Hello
Now the div is displayed on the page
Copy the code

The appendChild doubt

One element can only be inserted in one place

There are div#test1 and div#test2 in the page

let div = document.createElement('div') 
test1.appendChild(div) 
test2.appendChild(div)  
// Create a div element and insert it into the other two div elements
// Where will the newly created div element end up?
Copy the code
  • Where does the final div appear?

    • Option 1, test1
    • Option 2, test2
    • Option 3, inside test1 and inside test2
  • Answer: 👉 finally div appears in test2

    Because an element can’t appear in two places without making a copy

    The same way: send son Guanyin, send a child to the first family, and then send him to the second family, where is the final birth? A: The second family because a child can only have one biological family

The sample

Try adding elements to two places in sequence with appendChild (you can’t insert one element in more than one place)

let div1 = document.createElement('div')  
let text1 = document.createTextNode('hello')
div1.appendChild(text1)  
div1.style.backgroundColor = 'white'
div1.style.fontSize = '100px'
// There is a 
      
hello
element in memory. The background is white and the font is 100 pixels
// Insert the div1 element into head and body first document.head.appendChild(div1) document.body.appendChild(div1) // Finally, the div1 element will only appear in the body Copy the code

Copy the element so that it is inserted in multiple places

Use “cloneNode” cloneNode MDN

let div2 = div1.cloneNode(true)  
// true Deep copy: all descendants of the node will be cloned. // false Shallow copy: only the node itself will be cloned
document.head.appendChild(div1)
document.body.appendChild(div2)
Copy the code

delete

The two methods

// Old method 👇
parentNode.removeChild(childNode)  // The parent node must be found to remove the child node (anti-human)

// New method 👇
childNode.remove()  // IE is not supported (compatibility issues)
Copy the code

Temporary discussion: Why is IE always independent?

  • In fact, in the beginning, Internet Explorer was really the best browser. Other browser companies came up with “standards” to counter IE
  • So it’s not that IE became independent, it’s that standards came out too late
  • There were no standards when IE was dominant. Internet Explorer also doesn’t know the content of the standard in advance. And some of the content in the standard will deliberately with IE written in reverse
  • For example, IE invented innerText, and the standard was created to say that instead of innerText you should use textContent (which caused developers to write both 😭).
  • So it’s not necessarily IE trying to be independent. Could it be “standard” trying to be bad? ! (🤔 Blind child you found hua Dian)

The old method

// create div1 and clone div2
let div1 = document.createElement('div')  
let text1 = document.createTextNode('hello')
div1.appendChild(text1)
let div2 = div1.cloneNode(true)

// Insert div1/div2 elements into head/body, respectively
document.head.appendChild(div1)
document.body.appendChild(div2) 

// Delete the node again
div1.parentNode.removeChild(div1)
div2.parentNode.removeChild(div2)

// Can I add it back after I delete it?
// Yes. Since nodes are still in memory after being deleted, they can be added back
document.body.appendChild(div2)  
Copy the code

The new method

// create div1 and clone div2
// Insert div1/div2 elements into head/body, respectively

// Delete the node again
div1.remove()
div2.remove()

// Can I add it back after I delete it?
// Yes. Since the node is still in memory after being deleted, it can be added back to the same method
document.body.appendChild(div2)
Copy the code

Because [ele.remove()] was invented later, it is not compatible with IE

thinking

  • If a node is removed from the page (DOM tree)
  • Can it come back to the page again?
    • Answer: Yes. (See above for examples)
    • It’s just moved out, not completely wiped out, so it can still be in JS memory

How to kill an element completely

When an element is deleted, it disappears completely, does not exist in memory, and cannot be added back to the page

// Get rid of the element completely by moving it out of the page first
div1.remove()
div2.remove()  
Div1 /div2 are stored in memory
div1 = null
div2 = null  
Div1 /div2 is disconnected from memory and will be garbage collected
Copy the code

Change 💡

Change attributes

Write standard attributes

To change the class

Early JS objects could not have a “reserved word” as a key

div1.if  
// The parser of the JS engine sees if as an if statement, when in fact if is a key of the object div1
// This leads to ambiguity
// So JS does not accept "reserved words (JS keywords...)" As a key

div1.class = "red"  // Failed to modify
// Class is also a JS keyword, so it cannot be used
// Create a new name for the label class
Copy the code

The correct formula is 👇

Note: every time you use className to change the className, it overwrites the previous className

// If you just want to append the class name
div.className = 'red blue'  // Use className to write all class names
div.classList.add('red')    // Or append the class name to 👈
Copy the code
div.classList  // You can view an array of existing class names for the div element
Copy the code

Change a style
div.style = 'width:100px; color:blue; '  // Full coverage
div.style.width = '200px'              //
div.style.backgroundColor = 'white'    // Pay attention to the case of "hump name"
Copy the code

JS does not support key values with hyphen –

div.style.background-color    // ❌ is interpreted as a minus sign
div.style['background-color'] // ⭕ if the key contains a hyphen, only the form of parentheses ([]) can be used
div.style.backgroundColor     / / ✅
Copy the code

Change data – * attributes

There was a time when you needed to add custom attributes to an element. Almost no one uses it now (library developers might use it)

// Add custom attributes
div.setAttribute('data-x'.'test')  // <div data-x="test"></div>
div.dataset.xx = 'sam'              // <div data-xx="sam"></div>

// Get the attribute value of the custom attribute
div.getAttribute('data-x')   // test  
div.dataset.xx               // sam

// Modify the value of the custom attribute
div.dataset.xx = 'jack'      
Copy the code

Read standard attributes

div.id
div.classList
a.href 
// 👆 most attributes are one-to-one correspondence, directly read can be
Copy the code
Gets the original property value

Don’t want to be processed by the browser

div.getAttribute('class')
div.classList

a.getAttribute('href')
a.href
Copy the code

Either method will work, but the values may be slightly different (in most cases both methods will get the same result)

  • One is simply written, “XXX. Attribute name”, but the value may be processed

  • One is longer, “xxx.getAttribute(‘ attribute name ‘),” which is longer but ensures a more accurate and safer result

Example: a labelA special case 👇
<a id=test href='/xxx'></a>
Copy the code
console.log(test.href)  / / browser to completion the domain name https://null.jsbin.com/xxx
Copy the code

If you use the js property directly, read out the value. The results may be processed by the browser

Change the event handler function

Div. onclick defaults to null

Online code compilation

<div id="test">test</div>
Copy the code
console.log(test.onclick)  // null 
Copy the code
test.onclick = () = > {
  console.log('hi')}Copy the code
test.onclick = function(x){
  console.log(this)  // this: test
  console.log(x)     // x: event
}
Test.onclick. call(test, event)
// So this and event are actually called by the browser when the user clicks
Copy the code
  • Each element has an onclick attribute, which defaults to NULL
  • Clicking div by default does nothing
  • But if you change div.onclick to a function fn
    • So when you click on div, the browser will call this function
    • And fn.call(div, event)
      • Div will be called this (if you want to use this you can’t use arrow function, you must use function)
      • The event contains all the information about the click event, such as coordinates

div.addEventListener

Onclick is an updated version of div.onclick, and the rest of the class will focus solely on DOM events

  • Div.onclick can write only one function (all operations performed when clicked must be written in one function)
  • Div.addeventlistener can write an infinite number of functions (all operations performed when clicked can be written as different functions, very friendly for complex operations)

To change the content

Modify text content

div.innerText = 'xxx'    // It was invented by IE in the early days
div.textContent = 'xxx'  // As stipulated in the "standards"
Copy the code
  • There is little difference between the two
  • Almost all browsers now support both

To change the HTML content

Online code compilation

div.innerHTML = ' important content ' 
Copy the code
  • InnerText: All content is identified as text
  • InnerHTML: Parses the content, identifies the tag… (Note the length of the content. Exceeding a certain limit, such as 20000 characters, may cause the browser to freeze.)

To change the label

div.innerHTML = ' '      / / empty first
div.appendChild(div2)   // Add the content
Copy the code

To my father

Trying to find a new dad

newParent.appendChild(div)  // Add div directly to the new parent node, and the div in the previous parent node disappears automatically
Copy the code
  • Just like that. Just disappear from where you came from

check

Look up dad

node.parentNode 
/ / or
node.parentElement
Copy the code

Check the grandpa

node.parentNode.parentNode
Copy the code

Check the offspring

node.childNodes  // contains text nodes
/ / or
node.children    // [preferred] contains no text nodes
Copy the code

View online code

childNodes

Case 1

<ul id=test>
	<li>1</li>
  <li>2</li>
  <li>3</li>
</ul>
Copy the code
console.log(test.childNodes.length)   / / 7
Copy the code
  • The first child is a carriage return + space, which is finally reduced to a ** space ** (as we said in the beginning of HTML, any number of carriage return Spaces are reduced to a space).
  • The second child is: li
  • The third child node is: carriage return + space, finally reduced to a ** space **
  • The fourth child is: li
  • The fifth child node is: enter + space, finally reduced to a ** space **
  • The sixth child is: li
  • The seventh child node is: carriage return + space, finally reduced to a ** space **

Case 2

<ul id=test2><li>1</li><li>2</li><li>3</li></ul>
Copy the code
console.log(test2.childNodes.length)   // 3 // Because there are no carriage returns and Spaces
Copy the code

children

<ul id=test>
	<li>1</li>
  <li>2</li>
  <li>3</li>
</ul>
Copy the code
console.log(test.children.length)   // 3 // Even with carriage return Spaces, there are three child elements
Copy the code

So “Children check” uses children first

Consider: changes to element nodes

Do childNodes and Children change in real time when children change?

Online code: Children/childNodes

A: If the child elements change, the length ** of children/childNodes changes **

Online code: querySelectorAll

A: through document. QuerySelectorAll collection for child elements. If the children change, the length of the set doesn’t change. QuerySelectorAll does not change itself in real time based on elements. After you get it once, it doesn’t change

Brothers and Sisters

There is no API to get the siblings of any element directly, only the parent element and then the child element

node.parentNode.childNodes   // parentNode can be interchangeable with parentElement
node.parentNode.children     / / same as above

// Find the problem: the above array contains itself, and the requirement is that as long as the sibling element, filter itself // can only be traversed
// children traverses to exclude themselves
// childNodes traverses to exclude itself and all text nodes (more troublesome)
Copy the code

case

let div2 = document.getElementsByTagName('div') [1]
// How many siblings does div2 have
let siblings = []
let c = div2.parentElement.children // Get all of your father's children first, then iterate over them to exclude yourself
for(let i = 0; i > c.length; i++){
  if(c[i] ! == div2){ silblins.push(c[i]) } }Copy the code

Look at the first child

node.firstChild    // node.parentNode.children[0]
Copy the code

Look at the last child

node.lastChild
Copy the code

Check out the last brother

Closest sibling node (elder brother)

node.previousSibling          // If the previous node was a text node (space, carriage return...) , you get the text node
node.proviousElementSibling   // Avoids text nodes and only looks for element nodes
Copy the code

Add: [nodeType](# nodeType nodeType)

Check out the next brother

Next sibling node nearest to oneself (younger brother)

node.nextSibling         // Next sibling node (including text node)
node.nextElementSibling  // Next element sibling node (contains element nodes only)
Copy the code

Iterate over all the elements in a div

Same logic as the previous “data structure-traversal tree” logic

DOM is a tree. All algorithms for “trees” in data structures can be used in the DOM

travel = (node, fn) = > {   // Consistent with the code logic for traversing tree nodes
  fn(node)
  if(node.children){ 
    for(1et i = 0; i < node.children.length; i++){ travel(node.children[i], fn) } } } travel(div1,(node) = > console.log(node) ) 
Copy the code
  • See how useful data structures can be

DOM manipulation is cross-threaded 📌

Often asked: Why is DOM manipulation slow?

Because DOM manipulation and JS are two different things.

DOM manipulation is cross-threaded

Browser Function division

In the JS World section, we talked about the division of browser functionality

  • Browsers have two important features: “rendering engine” and “JS engine”
    • Rendering engine: Specialized for rendering HTML and CSS
    • JS engine: Designed to execute JS
  • The two engines are in different threads and are not related to each other

Cross-thread operation

These two threads — each doing its job

  • JS engine, can not operate the page, can only operate JS (window object, object object, document object… And so on)

    • The Document object exists, but you can’t manipulate anything with it, it can only manipulate the Document object itself — only JS
  • Rendering engine, can’t manipulate JS, can only manipulate pages

  • That’s what it’s all about.

document.body.appendChild(div1)  
// The page is changed by executing the JS call. This violates the principle of "each in his own place" ❓❓
Copy the code

JS engine can only handle JS, rendering engine can only handle page

  • How do I make div appear on screen?
  • In theory, it can only appear in body memory
  • ❓❓ — [cross-thread communication](# cross-thread communication)

Cross-thread communication

  • When the browser finds that JS wants to add a div1 object to the body
  • The browser tells the rendering engine:
    • Add a new div element to the page
    • All attributes of the new div element are copied from the div1 object

So it’s not JS rendering and changing the page, it’s the browser rendering and changing the page

Illustrates cross-thread operations

  • Left [JS execution thread], middle [browser], right [render thread] are independent

  • let div = doc.createElement('div')  // Does not affect the page, only changes the memory of the JS execution thread
    div.textContent = 'hi'              // Does not affect the page (first change of text content)
    document.body.appendChild(div)      
    // When the browser detects that JS has added a div node to the body, the browser notifies the rendering engine.
    // The rendering engine is notified to add a div element to the body.. div.textContent ='sam'   
    // The browser finds that the text content in the div node has changed, so it tells the rendering engine to "slow" and repeat the operation (change the text content for the second time).
    Copy the code
  • A significant amount of time is spent in the “intermediate process”, the “browser notifies the rendering engine” process

    • This makes the: div operation much slower than any of the other single-threaded operations
    • “Second change of text content” should be notified to the rendering engine. So the “second change of text content” operation is definitely slower than the “first” operation
    • [thinking](# DOM slow?) : Slow execution, is this a disadvantage of modularity?

DOM operation slow ❓❗️

The Internet says that DOM operation is slow, in fact, only slower than JS operation, DOM operation is much faster than network request. For this part, you can read some articles:

  • Why is DOM slow
  • Why is DOM still so slow after 10 years of effort

Note that the articles on the Internet are not always correct, just for reference.

“Cross-thread operation, making execution slower”, is this a disadvantage of modularity? A 👇

  • This is slower, but allows for separate optimizations within each thread.

  • For example, rendering can be optimized separately in the rendering engine, without having to deal with the various variables of JS… Because you can’t see them, you don’t need to think about them

  • conclusion

    • “Modular” can make each piece of division, are relatively simple, easy to optimize, easy to replace
    • Despite the time lost, the “benefits of modularity” are more significant

The complete process of inserting a new label (life cycle)

The div goes through three processes (vue also has a life cycle: before, when, and after)

Before DIV1 goes into the page

  • All operations you do to DIV1 belong to the JS thread

When you put DIV1 on the page

  1. The browser will discover the intent of JS
  2. The render thread is told to render the div1 element on the page

Put div1 after the page

Why say something as seemingly meaningless as “maybe, maybe not”

  • Because different browsers have different logic
  • The following four points use Chrome as an example
  1. Anything you do to DIV1 can trigger a re-render

  2. Div1.id =’newId’ may or may not be re-rendered

    • For example, if the changed ID has a CSS style, it will trigger a re-rendering
  3. Div1.title = ‘new’, even if the title is changed, it may or may not be re-rendered

    • It seems that changing the title should not affect the page. In fact, the title is sometimes rendered inside the page

    • For example, 👇

      <div title='titleHi'></div>
      <style>
        div::after{ content: attr(title); }   /* The page displays' titleHi '*/
      </style>
      <! The title attribute of the div is retrieved from the pseudo-element content of the div. If you change the title of the div, the page will be rerendered.
      Copy the code
  4. If you do div1 multiple times in a row, the browser may or may not merge it into one operation (as mentioned in the previous animation).

    • Required animation: Taper the width of the test element from 100 px to 200 px

    • See the link for the code. Why doesn’t animation happen when I write this?

      • In a short period of time, two operations were performed on the classList of this element (adding the class name twice)
      • JS thinks that executing twice and rendering twice is a waste of time, why not merge and render once to save rendering time
      • Animation effects cannot be displayed due to merging.
    • How can we not merge and demonstrate operational effectiveness

      • test.classList.add('start')
        // Execute one more step
        test.clientWidth  
        // Get the client width of test. This code may seem innocuous, but it's not
        // Because the width is to be obtained, the operation above adding the class must be rendered immediately
        // So there is no merge operation (to show the effect of mobilization)
        test.classList.add('end')
        Copy the code
    • Read width in the middle, causing JS to render start, then tell you the width, and render end.
    • And because there’s a CSS transition in the middle, there’s an animation

This is actually a very profound point, and few people can analyze the reason so clearly

Ask questions

let div = doc.createElement('div')  
div.textContent = 'hi'          // Rerender is not triggered
document.body.appendChild(div)  // when div is inserted into the page. div.textContent ='sam'   // After a div is inserted into the page, modifying the text content of the div must trigger a re-rendering
Copy the code

After the div inserts the page

  • Modifying the text content of a div must trigger a rerendering
  • Does “changing all attributes of the div trigger rerendering”?

The sample code

  • In HTML, the div element has three different attributes:id,x,data-x, the property values aretest
  • JS, get the div element as div1, and then change the values of these three attributes tofrank
  • Will the final div element on the page have all three attributes changed?
    • idModified successfully.xFailed to modify.data-xModify the success

Modifiable properties, is there a pattern?

  • If the property is in standard properties or data properties
  • The browser will automatically synchronize the changes to the rendered page
  • Id is a standard attribute, data-x is a data attribute, and x is a nonstandard attribute, and changing it does not affect the page

To summarize the criteria for “attribute synchronization”, [see below](# attribute synchronization)

Attribute synchronization

Standard properties

  • Changes to div1’s standard properties are automatically synchronized to the page by the browser
  • Id, className, title, etc. (if you change it, it will change directly)

Data – * attributes

  • Same as above

Nonstandard attribute

  • Changes to non-standard attributes will only remain in the JS thread
  • It doesn’t sync to the page
  • For example, the X property, sample code

revelation

  • If you want to customize attributes that are synchronized to the page, use data- as a prefix (data attributes)

  • Don’t use attributes like x

graphic

  • Div [standard attribute], automatic synchronization
  • Div [data attribute], automatic synchronization
    • [x property] in [data property], automatic synchronization
  • Div x property, what is it, roll

Supplement:

  • The properties in the JS thread are called “properties” and the attributes in the render thread are called “Attributes” ([contrast](# Property vs Attribute))
  • So the element.getAttribute () API gets the attributes in the page

Property vs Attribute

The property attribute

  • All properties of div1 in the JS thread, called div1’s property

    div1.style
    div1.id
    div1.className
    Copy the code

Attribute is also an attribute

  • The attribute that div1 corresponds to in the rendering engine is called an attribute

    <div id="test" class="test" data-x="test"></div>
    Copy the code

The difference between

  • Most of the time, property and attribute with the same name have the same value
  • But if theNot a standard propertySo they’re only going to be equal at the beginning
    • The nonstandard property x starts out equal. Later, the JS thread changed the value of x, but the renderer thread did not know, resulting in the inequality
  • But pay attention toAttribute Supports only character strings
    • The value of the tag attribute in the page can only be a string,<div id=1> </div>Id =1 in is also just the string 1 with the quotes omitted
  • Property supports strings, booleans, and so on