preface

We don’t have much of a chance to make an appearance in real projects, and some oF the apis we’ve never heard of. Here are some of the few that are out of the window.

Element.classList

Element.classList is a read-only property that returns a real-time DOMTokenList collection of an Element’s class attributes. ClassName is a more convenient way to access an element’s classList than using element.className as a whitespace delimited string. Common apis are as follows:

  • Add: Adds the specified class value. If these classes already exist in an element’s attribute, they are ignored.
  • Remove: deletes the specified class value.
  • Toggle: to switch classes; That is, remove the class if it exists, or add it if it doesn’t.
  • Contain: Checks whether the element’s class attribute contains the specified class value
  • Replace: Replace an existing class with a new class.

We could manipulate the DOM like this before element. classList didn’t come up

/* Add the class method */
function add(element, className) {
  if(!new RegExp("(^|\\s)" + className + "(\\s|$)").test(element.className)) element.className += ' ' + className;
}
/* Remove the class method */
function remove(element, className) {
  element.className = element.className.replace(new RegExp("(^|\\s)" + className + "(? =(\\s|$))"."g"), ' ');
}
/* Toggle class methods */
function toggle(element, className) {
    if(new RegExp("(^|\\s)" + className + "(\\s|$)").test(element.className)){
        element.className = element.className.replace(className,' ')}else{
        element.className = element.className.trim() + ' '+ className; }}/* Determine whether a class method */ is included
function contain(element, className) {
    return element.className.indexOf(className)>- 1
}
/* Replace the existing class */ with a new class
function replace(element, oldClassName,newClassName) {
    element.className = element.className.replace(oldClassName,newClassName)
}
Copy the code

After the appearance of element. classList, we manipulate the DOM like this

  • Add a class class to the element
element.classList.add( className )
Copy the code
  • Removes a class from the element
element.classList.remove( className )
Copy the code
  • Toggles a class on the element
element.classList.toggle( className )
Copy the code
  • Determines whether the element contains a class class
element.classList.contain( className )
Copy the code
  • Replace an existing class with a new class
element.classList.replace( oldClass, newClass )
Copy the code
  • Returns the class corresponding to the index


document.querySelector('.a').classList.item(0) // a

document.querySelector('.a').classList.item(1) // b

document.querySelector('.a').classList.item(2) // c

document.querySelector('.a').classList.item(3) // null
Copy the code

Element.getBoundingClientRect

Element. GetBoundingClientRect () method returns the Element size and its position relative to the viewport

The return value is a DOMRect object that is the set of rectangles returned by the element’s getClientRects() method, which is the CSS border size of the element. The result is the smallest rectangle that contains the entire element and has the left, top, right, bottom, x, y, width, and height read-only attributes in pixels that describe the entire border. Properties other than width and height are evaluated relative to the top left corner of the view window. Empty border boxes are ignored. If all element borders are empty, the rectangle returns 0 width, 0 height, and the values left and top are the top-left values of the first CSS box (in content order).

When the bounding rectangle is evaluated, scroll operations within the viewport region (or other scrollable elements) are taken into account, that is, when the scroll position changes, the values of the top and left attributes change immediately (thus, their values are relative to the viewport, not absolute). If you need to get a value relative to the top left corner of the entire page, just add the current scroll position to the top and left attributes (via window.scrollx and window.scrolly). This will get a value independent of the current scroll position. From Element. GetBoundingClientRect – MDN

We can get these data for our logic

function getBoundingClientRect (element) {
    let rect = element.getBoundingClientRect();
    return {
        left: rect.left,// The distance from the left side of the element to the left side of the window
        top: rect.top,// Distance from the top of the element to the top of the window
        right: rect.right,// The distance from the right side of the element to the left side of the window
        bottom: rect.bottom,// The distance from below the element to the top of the window
        width: rect.width,// Is the width of the element itself
        height: rect.height// Is the height of the element itself}}Copy the code

Element.insertAdjacentHTML

The insertAdjacentHTML() method parses the specified text into an Element and inserts the resulting node into the specified location in the DOM tree. It does not reparse the element it is using, so it does not destroy existing elements within the element. This avoids the extra serialization step and makes it faster than using innerHTML directly.

Grammar: element. InsertAdjacentHTML (position, text)

  • position

    A DOMString representing the position of the inserted content relative to the element and must be one of the following strings:

    • beforebegin: precedes the element itself.
    • afterbegin: before inserting the first child node inside the element.
    • beforeend: After the last child node is inserted inside the element.
    • afterend: comes after the element itself.
  • text

    Is a DOMString to be parsed as AN HTML or XML element and inserted into the DOM tree.

Visualization of location names

<! -- beforebegin --> 
<p> 
<! -- afterbegin -->
foo
<! -- beforeend -->
</p>
<! -- afterend -->
Copy the code

Note: beforebegin and Afterend positions work only if the node is in the tree and the node has a parent element.

Sometimes we want to insert a DOM string directly into a DOM element on a page. We want jQuery’s append function to inject DOM strings into the DOM

Document. The createElement method implementation

// html 
      
    let ul = document.getElementById('ul'); for(let i=0; i<5; i++){let li = document.createElement('li') li.className = "item" li.innerHTML = `<p>${item}</p>` ul.appendChild(li) } Copy the code

    As you can see, frequent DOM manipulation is extremely performance unfriendly

    Element. InsertAdjacentHTML implementation

    // html 
          
      let ul = document.getElementById('ul'); let html = ' ' for(let i=0; i<5; i++){ html +=`<li class="item"><p>${item}</p></li>` } ul.insertAdjacentHTML('beforeend',html) Copy the code

      You only manipulate the DOM once

      Security issues

      When you use insertAdjacentHTML to insert user-entered HTML content, you need to escape it before you can use it.

      Use node.textcontent or node.insertadjacenttext () instead of this method if you want to just insert textContent (not HTML nodes). Because this does not require HTML interpreter conversion, performance is better.

      CustomEvent

      CustomEvent events are created by the program and can have any custom function events.

      CustomEvent is a constructor that creates a CustomEvent that can be actively triggered with window.dispatchevent

      Example:

      Implement localStorage listening

      • Localstorage. setItem Listens for: custom event setItemEvent
      • Localstorage. getItem Listens to: custom event getItemEvent
      • Localstorage. removeItem Listens for: custom event removeItemEvent
      
      // Listen for custom event setItemEvent
      localStorage.setItem = (Orgin= >{
          return function(key,value){
              let setItemEvent = new CustomEvent('setItemEvent', {detail: {setKey:key,value}})
              window.dispatchEvent(setItemEvent)
              Orgin.call(this,key,typeof value == 'string'? value : JSON.stringify(value))
          }
      })(localStorage.setItem)
      
      // Listen for the custom getItemEvent
      localStorage.getItem = (Orgin= >{
          return function(key){
              let result = JSON.parse(Orgin.call(this,key))
              let getItemEvent = new CustomEvent('getItemEvent', {detail: {getKey:key,value:result}})
              window.dispatchEvent(getItemEvent)
              return result 
          }
      })(localStorage.getItem)
      
      
      // Listen for the custom event removeItemEvent
      localStorage.removeItem = (Orgin= >{
          return function(key){
              let removeItemEvent = new CustomEvent('removeItemEvent', {detail: {removeKey:key}})
              window.dispatchEvent(removeItemEvent)
              Orgin.call(this,key)
          }
      })(localStorage.removeItem)
      
      Copy the code

      SetItem, getItem and removeItem of localStorage are rewritten without affecting their own functions, allowing us to listen to the three operations of localStorage.

      Listening to the

      / / localStorage. SetItem listening in
      window.addEventListener('setItemEvent'.function(e){
          console.log(e.detail)
      })
      
      / / localStorage. The getItem to monitor
      window.addEventListener('getItemEvent'.function(e){
          console.log(e.detail)
      }) 
      
      / / localStorage. RemoveItem listening in
      window.addEventListener('removeItemEvent'.function(e){
          console.log(e.detail)
      })
      Copy the code

      This example has practical application in hybrid app development, native Android or native IOS interacting with our JS, which is very helpful

      ParentNode.append

      The parentNode. append method inserts a set of Node objects or DOMString objects after the last child of ParentNode. The inserted DOMString object is equivalent to a Text node.

      Differences with Node.appendChild() :

      • Parentnode.append () allows DOMString objects to be appended, while Node.appendChild() only accepts Node objects.
      • Parentnode.append () returns no value, while Node.appendChild() returns the appended Node object.
      • Parentnode.append () can append multiple nodes and strings, whereas Node.appendChild() can append only one Node.

      If you want to insert DOMString DOM, you can choose element. InsertAdjacentHTML (position, DOMString), if you want to which can be inserted into the NODE NODE can also be inserted into the string, Parentnode.append ()

      var parent = document.createElement("div");
      var p = document.createElement("p");
      parent.append("Some text", p);
      console.log(parent);
      // <div>"Some text"<p></p></div>
      Copy the code

      Document.createDocumentFragment

      Create a new blank DocumentFragment.

      Grammar: let fragments = document. CreateDocumentFragment ()

      Description: Fragment is a reference to an empty DocumentFragment object.

      DocumentFragments are DOM nodes. They are not part of the main DOM tree. The usual use case is to create a document fragment, attach elements to the document fragment, and then attach the document fragment to the DOM tree. In the DOM tree, the document fragment is replaced by all of its child elements.

      Because the document fragment exists in memory, not in the DOM tree, inserting child elements into the document fragment does not cause page backflow (calculations of element position and geometry). Therefore, using document fragments generally results in better performance.

      Example:

      HTML

      <ul id="ul"></ul>
      Copy the code

      JavaScript

      var element  = document.getElementById('ul'); // assuming ul exists
      var fragment = document.createDocumentFragment();
      var browsers = ['Firefox'.'Chrome'.'Opera'.'Safari'.'Internet Explorer'];
      
      browsers.forEach(function(browser) {
          var li = document.createElement('li');
          li.textContent = browser;
          fragment.appendChild(li);
      });
      
      element.appendChild(fragment);
      Copy the code

      Results:

      Firefox
      Chrome
      Opera
      Safari
      Internet Explorer
      Copy the code

      reference

      Chinese Web API reference | MDN interface

      conclusion

      If you have a better idea, or don’t find the tool function you want, feel free to leave a comment

      Please point out any inaccuracies or errors in the article

      Previous articles:

      Front-end code optimization utility

      Practical tools and methods in front-end development

      Common application scenarios for front-end promises