1.DOM(Document Object Model)

Document Object Model

2. Get the element’s API

  • Windows. idXXX or direct idXXX, for instance:

  • document.getElementById('idxxx'), usually use the above method to get the element, for id name keyword such as:parentIn this way.
  • document.getElementsByTagName('div')[0]
  • document.getElemetsByClassName('red')[0]
  • document.querySelector('#idXXX'), is written the same way CSS selectors are written.
  • document.querySelectorAll('.red')[0]

You are advised to use the bottom two types. GetElement (s)ByXXX is used only when compatible with Internet Explorer. To get specific elements:

  • Get the HTML element: document.documentElement
  • Get the head element: document.head
  • Get the body element: document.body
  • Get window (window not element) : window
  • Get all elements: document.all, note that since this method was initially only available in Internet Explorer, other browsers have adopted it in the past. The document.all value is true only for IE, so it can be used to check whether the current browser is IE. For example:

In IE:In the Chorme:

2.1 Prototype chain of acquired elements

Get a random element on the page withconsole.dir()You can see the elementPrototype ->HTMLElement->Element->Node->EventTarget->ObjectComplete prototype chain. Here is:

Original address: github.com/Scott-YuYan…

  • The first layer:HTMLDivElement. Prototype -- Attribute common to all divs
  • The second layer:Htmlelement. prototype -- An attribute common to all HTML tags
  • The third layer:Prototype -- Common attributes in XML/HTML
  • The fourth floor:Prototype -- (Node is an interface) Common property of all nodes
  • The fifth layer:Eventtarget. prototype -- The most important function property: addEventListener
  • The last layer:Object.prototype

3. Add, delete, modify, and check nodes

3.1 Adding a Node

Create a label node:

  • let div1 = document.createElement('div')
  • document.createElement('style')
  • document.createElement('script')
  • document.createElement('li')

Create a text node

  • Text1 = document. The createTextNode () 'hello'

Insert text into the tag

  • div1.appendChild(text1)
  • InnerText ='ni hao' or div1.textContent='ni hao'
  • But it doesn’t workdiv1.appendChild('ni hao')

Insert into the page

  • The label created is in the JS thread by default and needs to be inserted intobodyorhead, will take effect
  • Document. The body. The appendChild (div) or existing elements. The appendChild (div)

Note, for example, that the page has div#test1 and div#test2

let div = document.createElement('div'); test1.appendChild(div); test2.appendChild(div); Q: Where does the final div appear? (test1? test2? Or both?)Copy the code

The answer is that in test2 only, the same element cannot appear in two places unless a copy is made, using div.clonenode (true)–true for deep copy, meaning that all descendants are copied together.

3.2 abridged point

Two forms:

  • Old way:Child. ParentNode. RemoveChild (child) - to find your father node, and then use delete his father node
  • New method, but not compatible with IE:child.remove()
  • After a node is deleted, it is just put in memory and can still be recovered. If the node is null:child = nullThe node is then removed completely by the garbage collection.
3.3 change node

Write standard attributes:

  • Class :div.className='red blue'
  • Change class: div. ClassList. The add () 'red'
  • Change style: div style = "width: 100 px; color:blue; '
  • Div. Style. width='200px'
  • Change case: div. Style. BackgroundColor = 'white' (- c is simplified as c)
  • Div. SetAttribute ('','')
  • Data -* attribute: div.dataset. X ='frank'

Read standard attributes:

  • div.classList / a.href
  • div.getAttribute('class')/a.getAttribute('href')

It works either way, with some slight differences:

<a href="/ XXX "id="aTarget">Copy the code

Change the event handler function

  • The div.onclick() function defaults to null, and clicking does nothing. If you change div.onclick() to call the function fn(), the function will be called via fn.call(div,event) when the div is clicked.

Change the text content:

  • div.innerText = 'xxx'
  • div.textContent = 'xxx'

Change the HTML content:

  • Div. InnerHTML = '<h2> secondary title </h2>' // is case-sensitive and consumes memory
3.4 check nodes
  • Check my father:node.parentNode | node.parentElement
  • Check my grandpa:node.parentNode.parentNode
  • Check the offspring:node.childNodes | node.children

Note:

LiTest < ul id = "" > < li > son < / li > < li > son < / li > < li > son < / li > < / ul >Copy the code

That would have beenSeven.childnodesThe reason is that you need to pay attention to the carriage return Spaces before and after. willliWrite it on one line, or usechildrenThis can be avoided.

  • Brothers and sisters:Node. ParentNode..childnodes | children also ruled out yourself
  • Check the first | last a child:node.firstChild | node.lastChild
  • Check on a | next siblings:Node. PreviousSibling | node. NextSibling -- -- this way will get text content
  • Check on a | next sibling element node:Node. PreviousElementSibling | node. NextElementSibling -- -- won't get into the text content this way

4. Why are DOM operations slow

The reason: DOM manipulation is cross-threaded. Browsers are divided into rendering engine and JS engine, JS engine can not operate pages, only JS, and rendering engine can not operate JS only render pages. When using the document. The body. The appendChild (div1) to add elements to the body, the browser found JS added div1 object inside the body, the browser will notify the rendering engine also add a div object. All attributes of the newly added div element are copied from the div1 object. 1. Why is DOM slow

5. Capture and bubble

Call events from the outside incapture– Invented by Netscape, called event from inside outThe bubbling– Schematic diagram of IE invention:

5.1 Adding an API for event binding
  • ie5*: dom.attachEvent('onlick',fn) / / the bubbling
  • Netscape: dom. AddEventListener (' click '. The fn)/ / capture
  • The W3C. dom.addEventListener('click',fn,bool)// if bool is empty or falsy, fn bubbles; if bool is true, FN captures

Ask the following code:

< div id = "ye" > < div id = "ba" > < div id = "er" > test < / div > < / div > < / div >Copy the code

When we click the test, does it count as ye ba er being clicked? If so, should ye or er be executed first? The answer is: not sure, because the results are different in different browsers. \ Quad continues to ask, then if I add both listening events and capturing events to the same object, what is the order of firing? The answer to the question is: who adds first, who executes first.

5.2 What is the difference between event. Target and event. CurrentTarget?
  • Event. target- The element that the user operates on
  • Event.currenttarget – The element that the programmer listens on
  • This is the event. The currentTarget

For example:

<span> Text </span> </div>Copy the code

When we add event listeners to div and the user clicks on text, e.target refers to span and event.currentTarget refers to div.

5.3 Canceling bubbling

For cases where you need to unbubble, you can use E.topPropagation, so that the browser does not continue to execute the outer binding functions, generally suitable for encapsulating some independent components. Note, however, that some events can and cannot be defrosted, for example:

  • Click events:

  • Mouse scroll events:

So how to prevent the mouse scroll event, for example:Code – CSS:

::-webkit-scrollbar {
    display: none;
}
Copy the code

Code – js:

x.addEventListener('wheel', (e)=>{
  e.preventDefault();
});

x.addEventListener('touchstart',(e)=>{
  e.preventDefault();
});
Copy the code

6. Customize events

Earlier we mentioned the basic bubbling and capturing events, so the browser comes with over 100 events. Look at MDN- Events to see over 100 events included in the browser. In addition, we can also customize events, for example (again using the HTML in 5.1) :

<script> let ye = document.querySelector("#ye"); ye.addEventListener('click',()=>{ const myEvent = new CustomEvent('myEvent',{ detail:{'name':'zhangsan',}, Bubbles :true,// sets the bubble cancelable:false,// sets whether the bubble can be cancelled}) ye.dispatchEvent(myEvent)}) ye.addEventListener('myEvent',(event)=>{ console.log(event.detail); }) </script>Copy the code

7. Event delegation

Event delegation, as the name suggests, is to delegate an event that should be done by an event listener to another object. For example, the following scenario:

  • Scenario 1: You need to add click events to 100 buttons. What do you do?
<div id="outer">
    button#id$*100
</div>
Copy the code

Delegate listening events to the outer layer of button:

<script>
    let outer = document.querySelector("#outer");
    outer.addEventListener('click',(event)=>{
        let target = event.target;
        if (target.tagName.toLowerCase() === 'button'){
            console.log(target.id)
        }
    })
</script>
Copy the code
  • 2. Scenario 2 requires listening for events that do not exist

For example:

<div id="outer">
</div>
<script>
    let outer = document.querySelector("#outer");
    const button = document.createElement("button");
    button.textContent = 'click';
    setTimeout(()=>{
        outer.appendChild(button);
    },1000)
</script>
Copy the code

Click does not exist on the page, so it is also possible to delegate event listeners to external elements:

    outer.addEventListener('click',(event)=>{
        const tag = event.target;
        if (tag.tagName.toLowerCase() === 'button'){
            console.log(tag.innerText)
        }
    })
Copy the code

The advantages of doing this are: 1) saving the number of listeners and 2) listening for dynamically generated elements.

8. Synchronize attributes

  • Standard attributes: Changes to div standard attributes are synchronized to the page by the browser, for exampleId, className, title
  • data-*Attributes: same as above
  • Changes to nonstandard properties will only stay in the JS thread and will not be synchronized to the page. For example:
<div id="test" x="test" data-x="test"></div> function changeAttr() { let div1 = document.querySelector('#test'); div1.id = 'newTest'; div1.dataset.x = 'newTest'; Div1. x = 'newTest'; // No synchronization past}Copy the code

After the operation:You can see that the value of the nonstandard attribute X has not changed.

8.1 the property vs attribute
  • Property: all properties of div1 in the JS thread, called div1’s property
  • Attribute attribute: The attribute of the tag div1 corresponds to in the rendering engine. It is called an attribute

Differences between the two:

  • The two are mostly the same, but only at the beginning if they are not standard attributes
  • Attribute supports only strings, while property supports strings, Booleans, and other types