Detailed explanation of several API examples commonly used in advanced javascript front-end development

Detailed explanation of several API examples commonly used in advanced javascript front-end development

MutationObserver

MutationObserver is an interface that can monitor changes in DOM structure.

MutationObserver will be notified when any changes occur in the DOM object tree.

API

MutationObserver is a constructor that accepts a callback parameter, which is used to handle the callback function of node changes and returns two parameters:

mutations : list of node change records (sequence<MutationRecord>)

observer : Constructs a MutationObserver object.

The MutationObserver object has three methods, as follows:

observe : Set the observation target, accepts two parameters, target: observation target, options: set observation options through object members

disconnect : Stops the observer from observing any changes

takeRecords : Clears the record queue and returns its contents

//Select a node to be observed var targetNode = document.getElementById('root') 
// Set observer configuration options var config = { attributes: true, childList: true, subtree: true } 
// Function to be executed when a node changes var callback = function (mutationsList, observer) {
  for (var mutation of mutationsList) {
    if (mutation.type == 'childList') {
      console.log('A child node has been added or removed.')
    } else if (mutation.type == 'attributes') {
      console.log('The ' + mutation.attributeName + ' attribute was modified.')
    }
  }
} 
// Create an observer instance and associate it with the callback function var observer = new MutationObserver(callback) 
//Use the configuration file to observe the target node observer.observe(targetNode, config) 
// Stop observing observer.disconnect()

The options parameter in the observe method has the following options:

childList : Set to true to observe changes in the target child nodes, such as adding or deleting the target child nodes, but not modifying the child nodes and their descendants.

attributes : Set to true to observe changes in target attributes

characterData : Set to true to observe changes in target data

subtree : Set to true, changes to the target and its descendants will be observed

attributeOldValue : If the attribute is true or omitted, it is equivalent to setting it to true, indicating that the target attribute value before the change needs to be recorded. If attributeOldValue is set, the attributes setting can be omitted.

characterDataOldValue : If characterData is true or omitted, it is equivalent to setting it to true, indicating that the target data before the change needs to be recorded. If characterDataOldValue is set, the characterData setting can be omitted.

attributeFilter : If not all attribute changes need to be observed, and attributes is set to true or ignored, then set a list of attribute local names (without namespace) that need to be observed

Features

MutationObserver has the following features:

  • It waits for all script tasks to complete before running, that is, it uses asynchronous mode
  • It encapsulates DOM change records into an array for processing, rather than processing DOM changes individually one by one.
  • It can observe all changes that occur in DOM nodes, or a certain type of changes

When the DOM changes, the MutationObserver event is triggered. However, it is essentially different from events: events are triggered synchronously, that is, DOM changes will immediately trigger the corresponding events; MutationObserver is triggered asynchronously, and it will not be triggered immediately after the DOM changes, but will be triggered after all current DOM operations are completed.

For example, if you insert 1000 paragraphs (p elements) into a document continuously, 1000 insertion events will be triggered continuously, and the callback function of each event will be executed, which is likely to cause browser lag. MutationObserver is completely different. It will only be triggered after all 1000 paragraphs have been inserted, and it will only be triggered once. This reduces frequent changes to the DOM and greatly benefits performance.

IntersectionObserver

When developing web pages, you often need to know whether an element has entered the "viewport", that is, whether the user can see it.

The traditional implementation method is to listen to the scroll event, call the getBoundingClientRect() method of the target element, obtain its coordinates corresponding to the upper left corner of the viewport, and then determine whether it is within the viewport. The disadvantage of this method is that due to the intensive occurrence of scroll events, the amount of calculation is large, which can easily cause performance problems.

There is a new IntersectionObserver API that can automatically "observe" whether an element is visible, which is supported by Chrome 51+. Since the essence of visible is that the target element and the viewport produce an intersection area, this API is called "intersection observer".

API

IntersectionObserver is a constructor provided by the browser natively. It accepts two parameters: callback is the callback function when visibility changes, and option is a configuration object (this parameter is optional).

var io = new IntersectionObserver(callback, option)
// Start observing io.observe(document.getElementById('example')) 
// Stop observing io.unobserve(element) 
// Close the observer io.disconnect()

If you want to observe multiple nodes, you need to call this method multiple times.

io.observe(elementA)
io.observe(elementB)

When the visibility of the target element changes, the observer's callback function is called. The callback is usually triggered twice. Once when the target element just enters the viewport (begins to be visible), and once when it completely leaves the viewport (begins to be invisible).

var io = new IntersectionObserver((entries) => {
  console.log(entries)
})

The callback function's parameter (entries) is an array, each member of which is an IntersectionObserverEntry object. For example, if the visibility of two observed objects changes at the same time, the entries array will have two members.

time : The time when visibility changes, a high-precision timestamp in milliseconds

target : The target element being observed, a DOM node object

isIntersecting : Is the target visible?

rootBounds : Information about the rectangular area of ​​the root element, the return value of the getBoundingClientRect() method. If there is no root element (that is, scrolling directly relative to the viewport), null is returned.

boundingClientRect : Information about the rectangular area of ​​the target element

intersectionRect : Information about the intersection area between the target element and the viewport (or root element)

intersectionRatio : The visible ratio of the target element, that is, the ratio of intersectionRect to boundingClientRect. It is 1 when it is completely visible and less than or equal to 0 when it is completely invisible.

For example

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style>
      #div1 {
        position: sticky;
        top: 0;
        height: 50px;
        line-height: 50px;
        text-align: center;
        background: black;
        color: #ffffff;
        font-size: 18px;
      }
    </style>
  </head> 
  <body>
    <div id="div1">Home</div>
    <div style="height: 1000px;"></div>
    <div id="div2" style="height: 100px; background: red;"></div>
    <script>
      var div2 = document.getElementById('div2')
      let observer = new IntersectionObserver(
        function (entries) {
          entries.forEach(function (element, index) {
            console.log(element)
            if (element.isIntersecting) {
              div1.innerText = 'I'm out'
            } else {
              div1.innerText = 'Homepage'
            }
          })
        },
        {
          root: null,
          threshold: [0, 1]
        }
      ) 
      observer.observe(div2)
    </script>
  </body>
</html>

Compared with getBoundingClientRect, its advantage is that it will not cause redrawing and reflow.

Lazy loading of images

The principle of lazy loading of images is mainly realized by the core logic of judging whether the current image has reached the visible area. This saves bandwidth and improves web page performance. Traditional breakthrough lazy loading is achieved by listening to scroll events, but scroll events will be triggered many times in a short period of time, seriously affecting page performance. To improve page performance, we can use IntersectionObserver to implement lazy loading of images.

const imgs = document.querySelectorAll('img[data-src]')
const config = {
  rootMargin: '0px',
  threshold: 0
}
let observer = new IntersectionObserver((entries, self) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      let img = entry.target
      let src = img.dataset.src
      if (src) {
        img.src = src
        img.removeAttribute('data-src')
      }
      // Unobserve self.unobserve(entry.target)
    }
  })
}, config)
imgs.forEach((image) => {
  observer.observe(image)
})

Infinite Scroll

The implementation of infinite scroll is also simple.

var intersectionObserver = new IntersectionObserver(function (entries) {
  // If it is not visible, return if (entries[0].intersectionRatio <= 0) return
  loadItems(10)
  console.log('Loaded new items')
})
 
// Start observing intersectionObserver.observe(document.querySelector('.scrollerFooter'))

getComputedStyle()

DOM2 Style adds a getComputedStyle() method to document.defaultView , which returns a CSSStyleDeclaration
An object (of the same type as the style property) containing the computed style of the element.

API

document.defaultView.getComputedStyle(element[,pseudo-element])
// or
window.getComputedStyle(element[,pseudo-element])

This method accepts two parameters: the element to get the computed style of and the pseudo-element string (such as ":after"). If no pseudo-element is needed, the second parameter can be null.

<!DOCTYPE html>
<html>
  <head>
    <style type="text/css">
      #myDiv {
        background-color: blue;
        width: 100px;
        height: 200px;
      }
    </style>
  </head>
  <body>
    <div id="myDiv" style="background-color: red; border: 1px solid black"></div>
  </body>
  <script>
    function getStyleByAttr(obj, name) {
      return window.getComputedStyle ? window.getComputedStyle(obj, null)[name] : obj.currentStyle[name]
    }
    let node = document.getElementById('myDiv')
    console.log(getStyleByAttr(node, 'backgroundColor'))
    console.log(getStyleByAttr(node, 'width'))
    console.log(getStyleByAttr(node, 'height'))
    console.log(getStyleByAttr(node, 'border'))
  </script>
</html>

Similarities and differences with style

The similarity between getComputedStyle and element.style is that both return CSSStyleDeclaration objects. The difference is:

element.style only reads the inline style of the element, that is, the style written in the style attribute of the element; while the style read by getComputedStyle is the final style, including inline style, embedded style and external style.

element.style supports both reading and writing. We can rewrite the style of an element through element.style. However, getComputedStyle only supports reading and not writing. We can read the style using getComputedStyle and modify the style using element.style

getBoundingClientRect

The getBoundingClientRect() method returns the size of an element and its position relative to the viewport.

API

let DOMRect = object.getBoundingClientRect()

Its return value is a DOMRect object, which is a set of rectangles returned by the getClientRects() method of the element, that is, the CSS border size of the element.

The result returned is the smallest rectangle that contains the entire element, and has read-only properties of left, top, right, bottom, x, y, width, and height that describe the entire bounding box in pixels. Properties other than width and height are calculated relative to the upper-left corner of the view window.

Application Scenario

1. Get the distance of the DOM element relative to the upper left corner of the web page

The previous writing method is to find the element through offsetParent to locate the parent element until it recursively reaches the top-level element body or html.

// Get the distance of the DOM element relative to the upper left corner of the web page function offset(el) {
  var top = 0
  var left = 0
  do {
    top += el.offsetTop
    left += el.offsetLeft
  } while ((el = el.offsetParent)) // There is a compatibility issue, need to be compatible return {
    top: top,
    left: left
  }
} 
var odiv = document.getElementsByClassName('markdown-body')
offset(a[0]) // {top: 271, left: 136}

Now according to the getBoundingClientRect API, it can be written like this:

var positionX = this.getBoundingClientRect().left + document.documentElement.scrollLeft
var positionY = this.getBoundingClientRect().top + document.documentElement.scrollTop

2. Determine whether the element is in the visible area

function isElView(el) {
  var top = el.getBoundingClientRect().top // The distance from the top of the element to the top of the visible areavar bottom = el.getBoundingClientRect().bottom // The distance from the bottom of the element to the top of the visible areavar se = document.documentElement.clientHeight // The height of the visible area of ​​the browser.
  if (top < se && bottom > 0) {
    return true
  } else if (top >= se || bottom <= 0) {
    // Invisible}
  return false
}

The above is the detailed content of several API examples commonly used in advanced front-end development of javascript. For more information about advanced front-end API examples, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Vue Element front-end application development front-end API interface encapsulation
  • Baidu map front-end web api example code with current location
  • Summary of 12 commonly used front-end UI frameworks
  • Example of using JS to automatically obtain addresses and longitude and latitude using Baidu Maps API
  • Example of requesting server-side API interface implemented by Vue

<<:  Significantly optimize the size of PNG images with CSS mask (recommended)

>>:  iFrame is a great way to use it as a popup layer to cover the background

Recommend

CSS shadow animation optimization tips

This technique comes from this article - How to a...

Analysis of HTTP interface testing process based on postman

I accidentally discovered a great artificial inte...

Detailed explanation of Apache website service configuration based on Linux

As an open source software, Apache is one of the ...

A detailed introduction to setting up Jenkins on Tencent Cloud Server

Table of contents 1. Connect to Tencent Cloud Ser...

Detailed explanation of long transaction examples in MySQL

Preface: The "Getting Started with MySQL&quo...

Mysql optimization techniques for querying dates based on time

For example, to query yesterday's newly regis...

Implementation of Docker Compose multi-container deployment

Table of contents 1. WordPress deployment 1. Prep...

Detailed explanation of this reference and custom properties in JavaScript

Table of contents 1. this keyword 2. Custom attri...

HTML css js implements Tab page sample code

Copy code The code is as follows: <html xmlns=...

VMware Workstation installation Linux (Ubuntu) system

For those who don't know how to install the s...