As a front end enthusiast, In my spare time to study for several foreign web site source code, find whether library, or a business code, with some interesting API, although peacetime work in some contact, but through this study, think it is necessary to sum up, after all, has been 2020 years, it’s time to update technical reserves, this paper mainly through the actual case Let’s take you to quickly understand the following knowledge points:

  • Observer Native Observer
  • Script tag Event Depth – Why events can still execute after removing script tags
  • Proxy/Reflect
  • Custom event
  • fileReader API
  • Fullscreen Fullscreen of a web page
  • Use of the URL API
  • Geolocation Use of the Geolocation API
  • Notifications browser native message Notifications
  • Battery Status Battery Status of the device

I’ll do some interesting examples of some of the apis, so let’s get started

1. Observer API

Observer is the built-in Observer of the browser, which mainly provides Intersection, Mutation, Resize, and Performance. The author focuses on Intersection Observer here.

1.1 Intersection computes the Observer

IntersectionObserver provides a method to asynchronously observe the intersecting state of the target element and its ancestor elements. When a IntersectionObserver object is created, it is configured to listen to the visible region of a given proportion in the root, and its configuration cannot be changed. Therefore, a given observer object can only be used to listen to the specific change value of the visible region. However, we can configure listening for multiple target elements in the same observer object.

To put it simply, the API asynchronously listens for the target element’s position within the root element and triggers a response event. We can use it to achieve more efficient lazy image loading, infinite scrolling and content buried point reporting. Let’s use an example to illustrate how to use it.

// 1. Define the observer and the observation callback
const intersectionObserver = new IntersectionObserver((entries, observer) = > {
    entries.forEach(entry= > { 
      console.log(entry)
      / /... Some operations
    }); 
   },
   {
    root: document.querySelector('#root'),
    rootMargin: '0px'.threshold: 0.5})// 2. Define the object to be observed
const target = documentQuerySelector (" target "); intersectionObserver.observe(target);Copy the code

This code implements a basic Intersection Observer, even though the existing code doesn’t have any real functionality. Here’s what the parameters used in the code mean:

  • Callback IntersectionObserver the first argument to an instance of a callback that is triggered when the target element and the root element pass the threshold 🍌. The first parameter in the callback is the list of observed objects, which will be moved to if the observed object mutates. Each item in the list retains the location of the observer. The second parameter is the observer, the observer itself. Console print as shown below:

    Among themrootBoundsRepresents the location information of the root element,boundingClientRectRepresents the location information of the target element,intersectionRectRepresents the position information of the fork,intersectionRatioRepresents the visibility of the target element.

  • Configure the second parameter of the attribute IntersectionObserver instance, which is used to configure the listening properties. The following three properties are specified:

    • The specific ancestor element of the object on which root listens. If no value is passed in or null, the window for the top-level document is used by default.
    • RootMargin Calculates the rectangular offset added to the root bounding box when crossing, which can effectively narrow or expand the determination range of the root to meet the calculation requirements
    • thresholdsA list of thresholds, in ascending order, each threshold in the list is the ratio of the cross region to the boundary region of the listener. A Notification is generated when any threshold of the listening object is crossed. If the constructor does not pass in a value, the default value is 0. The description of the above properties may be difficult to understand literally, but I have taken a few sketches to give you an intuitive understanding:

      When we set rootMargin to 10px, our root will increase the influence range, but the target element will be monitored if it moves to the light red area. Of course, we can also set rootMargin to be negative to reduce the influence area. The supported values are percentages and px, as follows:

rootMargin: '10px'
rootMargin: '10%'
rootMargin: '10px 0px 10px 10px'
Copy the code

Thresholds can be understood as follows:

  • Disconnect () stops the IntersectionObserver object from listening
  • TakeRecords () returns all the observable IntersectionObserverEntry array of objects
  • Unobserve () stops IntersectionObserver from listening to a specific target element

Now that we know how to use it and the API, let’s look at a practical application that implements lazy image loading:

<img src="loading.gif" data-src="absolute.jpg">
<img src="loading.gif" data-src="relative.jpg">
<img src="loading.gif" data-src="fixed.jpg">

<script>
let observerImg = new IntersectionObserver(
(entries, observer) = > { 
    if (entries[0].intersectionRatio = 0) return
    entries.forEach(entry= > {
        // Replace with a formal image
        entry.target.src = entry.target.dataset.src;
        // Stop listening
        observer.unobserve(entry.target);
      });
    }, 
    {
      root: document.getElementById('scrollView'),
      threshold: 0.3});document.querySelectorAll('img').forEach(img= > { observerImg.observe(img) });
</script>
Copy the code

The above code implements a lazy image loading function. The real image is only loaded when 30% of the image enters the root element, which reminds me of the react-Lazyload image used in an advertisement placement report. You can also use it to achieve infinite scrolling, H5 parallax animation and other interesting interactive scenes.

1.2 Mutation Observer and Resize Observer

The Mutation Observer is mainly used to listen on DOM changes. It is also triggered asynchronously and is very listener friendly. The Resize Observer is primarily used to listen for changes in the size of elements. It has better performance and more granular control over the DOM than window.resize, which fires every time a window changes. It is called only before drawing or after laying out. The use and usage of the two apis are very similar, and the official data is complete. You can study them carefully.

2. Why the event can still execute after removing the script tag

This question is mainly asked by a friend before. At that time, my idea was to simply think that the code in the script was executed and bound to the DOM, and stored in the browser memory. Recently, I checked a lot of information and found an interesting explanation.

JavaScript interpreters execute scripts in blocks. This means that if the browser encounters ascript tag while parsing an HTML document stream, the JavaScript interpreter waits until the block of code is loaded, precompiles it, and executes it. So, by the time you start executing the code for this code block, the code block has already been parsed. At this point, the deletion from the DOM does not affect the code execution.

3. Proxy/Reflect

Proxy/Reflect is an API of ES6, which has appeared for several years, but it is less used in the project. If it is to do the work of the underlying architecture, it is recommended that we use it more. After all, vue/ React framework source code plays these apis like fire pure green, it is necessary to master it.

In fact, we can understand the usage of these apis very well by carefully reading the introduction of MDN or the article of Mr. Ruan Yifeng. Next, we will introduce these two apis and their application scenarios in detail.

3.1 the Proxy

Proxy can be understood as that a layer of “interception” is set up before the target object, and the external access to the object must pass this layer of interception first. Therefore, it provides a mechanism to filter and rewrite the external access. Proxy is used with Reflect in many scenarios. The usage is simple. Let’s look at the basic usage of Proxy:

const obj = {
   name: 'Xu Xiaoxi'.age: '120'
 }
 const proxy = new Proxy(obj, {
   get(target, propKey, receiver) {
    console.log('get:' + propKey)
    return Reflect.get(target, propKey, receiver)
   },
   set(target, propKey, value, receiver) {
    console.log('set:' + propKey)
    return Reflect.set(target, propKey, value, receiver)
   }
 })
 console.log(proxy.name) // Get :name Xu Xiaoxi
 proxy.work = 'frontend' // set:work frontend
Copy the code

The above code intercepts the obj object and redefines the read/write (GET /set) methods so that we can do additional operations when accessing the object.

Proxy properties such as Apply (intercepting a Proxy instance as a function call) and Construct (intercepting a Proxy instance as a constructor call) can be used for interception at different stages of an object operation, so I won’t give you any examples here. Let’s take a look at Proxy in action.

  • To read the index of a negative array

We usually operate on arrays in the forward direction. We cannot find arrays in the reverse direction by specifying a negative number, as shown in the figure below:

// The original
arr[arr.length - 1]
// Write after the proxy modification
arr[- 1]
Copy the code

The implementation code is as follows:

function createArray(. elements) {
  let handler = {
    get(target, propKey, receiver) {
      let index = Number(propKey);
      if (index < 0) {
        propKey = String(target.length + index);
      }
      return Reflect.get(target, propKey, receiver); }};lettarget = []; target.push(... elements);return new Proxy(target, handler);
}
Copy the code

We can find that the above code uses proxy to proxy the array read operation, in the internal packaging support negative value lookup function, of course, we can also do not use proxy to achieve the same function, here refer to the implementation of Teacher Ruan Yifeng.

  • Use proxy to implement more elegant validators

If else or switch to verify the value of a form, you can also use a proxy to do this gracefully.

const formData = {
   name: 'xuxi'.age: 120.label: ['react'.'vue'.'node'.'javascript']}/ / validator
 const validators = {
   name(v) {
     // Verify that name is a string and is longer than 3
     return typeof v === 'string' && v.length > 3
   },
   age(v) {
     // Verify that age is a value
     return typeof v === 'number'
   },
   label(v) {
     // Verify that the label is an array and has a length greater than 0
     return Array.isArray(v) && v.length > 0}}// Proxy verification object
 function proxyValidator(target, validator) {
  return new Proxy(target, {
    set(target, propKey, value, receiver) {
      if(target.hasOwnProperty(propKey)) {
        let valid = validator[propKey]
        if(!!!!! valid(value)) {return Reflect.set(target, propKey, value, receiver)
        }else {
          // Some other error business...
          throw Error(Value validation error${propKey}:${value}`)}}}})}Copy the code

With the above implementation pattern, we can implement validation when setting a value in the form. The usage is as follows:

let formObj = proxyValidator(formData, validators)
formObj.name = 333;   // Uncaught Error: Value verification Error name:f
formObj.age = 'ddd'   // Uncaught Error: Value verification Error age:f
Copy the code

In the above code, when an invalid value is set, the console will extract the error, and if in real business, we can give the user the appropriate warning.

  • Implement request interception and error reporting
  • Implement data filtering

I have written about these points in previous articles, so I won’t go into details here. You can also implement more flexible interception operations according to the actual situation. Of course, Proxy provides more than these apis, we can learn more advanced usage in MDN or other channels.

3.2 Reflect

Reflect is also a new API provided by ES6 to manipulate objects, and is more likely to be used in conjunction with a Proxy, as we’ve seen in the previous section. You can put some methods that are clearly internal to the language on the Reflect Object, and modify the results returned by some Object methods. The methods on the Reflect object correspond to the methods on the Proxy object. As long as the methods on the Proxy object correspond to the methods on the Reflect object.

4. Customize events

The CustomEvent API is a very interesting API, it’s very practical, and more importantly it’s very simple to learn, and it’s supported by most modern browsers. We can make any DOM element listen for and trigger custom events by doing the following:

// Add an appropriate event listener
dom1.addEventListener("boom".function(e) { something(e.detail.num) })

// Create and distribute events
var event = new CustomEvent("boom", {"detail": {"num":10}})
dom1.dispatchEvent(event)
Copy the code

Let’s look at the description of the parameters for CustomEvent:

  • Type The type name of the event, such as ‘boom’ in the code above.
  • CustomEventInitProvides the configuration information for the event, which has the following properties
    • Bubbles a Boolean value indicating whether or not the event bubbles
    • Cancelable A Boolean value indicating whether the event can be cancelled
    • Detail Data passed when the event is initialized

We can use dispatchEvent to trigger custom events. It can be used for a variety of purposes, such as creating observer mode, bi-directional data binding, or even in game development, such as the following example:

dispatch
detail
H5 game

5. fileReader

File API allows us in the browser can access the File data, such as the preview File, File information (such as File name, File content, File size, etc.), and can be realized in the front-end File download (use a canvas and window. URL. RevokeObjectURL some ability). Of course, we can also achieve a high user experience such as dragging and dropping upload files. Let’s look at a few practical examples.

  • Display thumbnail
function previewFiles(files, previewBox) {
    for (var i = 0; i < files.length; i++) {
      var file = files[i];
      var imageType = /^image\//;
      
      if(! imageType.test(file.type)) {continue;
      }
      
      var img = document.createElement("img");
      previewBox.appendChild(img); // Assume that "preview" is the div used to display the content
      
      var reader = new FileReader();
      reader.onload = (function(imgEl) { 
        return function(e) { imgEl.src = e.target.result; }; })(img); reader.readAsDataURL(file); }}Copy the code

The above code can display the uploaded image in the reviewBox container, of course, we can also based on this extension, using the canvas to draw the image to the canvas, and then the image compression, and finally upload the compressed image to the server. In this way, in fact, many tools are used in the website, such as online picture processing website, providing batch compression pictures, batch watermark and other functions, routines are similar, interested friends can try to study.

  • Encapsulate the file upload component

This author has written a detailed article before, here is not an example, the article address:

  • 3 minutes teach you to use native JS implementation with progress listening file upload preview component
  • Remember an old project with cross-page communication issues and front-end implementation of file downloads

6. Fullscreen

Fullscreen API is mainly for web pages can be full screen on a computer screen, it allows us to open or exit full screen mode, so that we can according to the need for the corresponding operation, for example, we commonly used web graphics editor or rich text editor, in order to allow the user to concentrate on the content design, we often provide full screen switch function for users. Since the full-screen API is relatively simple, let’s go straight to the code here:

// Enable full screen
document.documentElement.requestFullscreen();
// Exit the full screen
document.exitFullscreen();
Copy the code

The document.documentElement of the above code can also be replaced with any element you want to make full screen. By default. We can also through the document fullscreenElement to judge whether the current page in full screen state, to realize the switch screen effect. If we’re react developers, we can also wrap it into a custom hooks to implement business-specific full-screen toggles.

7. URL

The URL API is part of the URL standard, which defines the content that makes up an effective uniform resource locator and the APIS for accessing and manipulating urls.

There are many interesting things we can do with the URL component. For example, if we have a requirement to extract url parameters to pass to the background, the traditional approach is to write your own method to parse the URL string and return a Query object manually. But with the URL object, we can easily get URL parameters, as follows:

let addr = new URL(window.location.href)
let host = addr.host  // Obtain the host address
let path = addr.pathname  // Obtain the path name
let user = addr.searchParams.get("user")  // Get the value of user
Copy the code

If we convert the URL to a URL object, we can easily use the searchParams API to get the URL parameters without having to write a method ourselves.

On the other hand, if the website is more secure, we can also sort the parameters by natural numbers and then encrypt them and upload them to the back end. The specific code is as follows:

function sortMD5WithParameters() {
    let url = new URL(document.location.href);
    url.searchParams.sort();
    let keys = url.searchParams.keys();
    let params = {}
  
    for (let key of keys) {
      let val = url.searchParams.get(key);
      params[key] = val
    };
    / /... Md5 encryption
    return MD5(params)
 }
Copy the code

8. Geolocation

Geolocation is a useful browser API that can be used to determine a user’s location on a website, to give the site a different presentation and enhance the user experience.

Here are some interesting examples to give you a sense of it:

  • Depending on the region, the site displays different themes:
  • E-commerce websites or content websites are often used to display different recommended content according to the user’s location. For example, if the user is in Xinjiang, he or she will be recommended with melon and fruit advertisements; if the user is in Beijing, he or she will be recommended with tourist attractions advertisements. Although it is often more complicated in practical application, it is also a kind of idea.

But there’s more to it than that. Programmers can use their imagination to do even more interesting things and make their websites smarter. Next, I write a piece of code based on the promise to get the user’s location:

function getUserLocation() {
    return new Promise((resolve, reject) = > {
      if(! navigator.geolocation) { reject() }else {
        navigator.geolocation.getCurrentPosition(success, error);
      }

      function success(position) {
        const latitude  = position.coords.latitude;
        const longitude = position.coords.longitude;
        resolve({latitude, longitude})
      }

      function error() {
        reject()
      }
    })
  }
Copy the code

The usage mode and results are shown in the figure below:

9. Notifications

The Notifications API enables web pages or applications to send Notifications at the system level that are displayed outside the page; This allows the Web application to send information to the user even if the application is idle or in the background.

Let’s take a practical example, for example, we have a website content update, notify the user, the effect is as follows:

Notification.requestPermission( function(status) {
  console.log(status); // Displays notifications only when the value is granted
  var n = new Notification("Gossip front", {body: "Build a CMS full-stack project from zero."}); // Display notifications
});
Copy the code

Of course, the browser’s Notification also provides us with four event-triggering apis for more complete control:

  • Onshow is triggered when a notification is displayed to the user (deprecated, but still usable in some browsers)
  • Onclick is triggered when the user clicks on the notification
  • Onclose is triggered when the notification is closed (deprecated, but still available for some browsers)
  • Onerror is emitted when an error has been notified

With such an event listener, we can control when a user clicks on a notification, redirect to the corresponding page or execute the related business logic. The following code looks like this:

Notification.requestPermission( function(status) {
  console.log(status); // Displays notifications only when the value is granted
  var n = new Notification("Gossip front", {body: "Build a CMS full-stack project from zero."}); // Display notifications
      n.onshow = function () { 
        // The logic to execute when the message is displayed
        console.log('show') 
      }
      n.onclick = function () { 
        // The logic to execute when a message is clicked
        history.push('/detail/1232432')
      }
      n.onclose = function () { 
        // Logic executed when the message is closed
        console.log('close')}});Copy the code

Of course, we need to obtain permission before using, the way is also very simple, you can learn in MDN.

10. Battery Status

The Battery Status API provides information about the charging level of the system and provides events to alert users to changes in the Battery level or charging Status. This can be used to adjust the application’s resource usage when the device’s battery is low, or to save changes in the application before the battery runs out to prevent data loss.

Previous versions of the Battery Status API provided several event listening functions to monitor changes in the Battery charge and whether the device is being charged, but these apis have been deprecated as follows:

  • Chargingchange Whether the monitoring device is charged
  • Levelchange Monitors the charge level
  • Chargingtimechange Changes the chargingtime
  • Dischargingtimechange Change of discharge time

Although some of these seemingly useful apis have been deprecating, I have tested them in Google, but to make our code more reliable, we can use other methods, such as using a timer to periodically check the power level and make different alerts to users.

Let’s look at the basic usage:

navigator.getBattery().then(function(battery) {
  console.log("Is it charging? " + (battery.charging ? "Yes" : "No." "));
  console.log("Power level:" + battery.level * 100 + "%");
  console.log(Charging time: + battery.chargingTime + " s");
  console.log(Discharge time: + battery.dischargingTime + "s");
});
Copy the code

Through getBattery we can get equipment battery information, this API is very useful, for example, we can in the user when the battery is low to disable the web animation or stop using some time-consuming tasks, or is for the user to do appropriate to remind, change, such as site color for playing video or live in the webapp, we can also use CSS to draw a electricity Quantity bar, when the power is out of emergency to remind the user. As a good website experience, this is not to be ignored.

reference

  • Introduction to ECMAScript 6 – Yifeng Ruan
  • MDN web English docs

The last

If you want to learn more H5 games, Webpack, node, gulp, CSS3, javascript, nodeJS, Canvas data visualization and other front-end knowledge and practical, welcome to join our technical group in the public number “Interesting Talk front-end” to learn and discuss together, and explore the boundary of the front-end.

More recommended

  • Front-end advanced from zero to one to achieve unidirectional & bidirectional linked list
  • Preliminary study of micro front-end architecture and my front-end technology inventory
  • Browser Cache Library Design Summary (localStorage/indexedDB)
  • Develop your own graph bed application using nodeJs
  • Implementing a CMS full stack project from 0 to 1 based on nodeJS (Part 1)
  • Implement a CMS full stack project from 0 to 1 based on nodeJS (middle) (source included)
  • CMS full stack project Vue and React (part 2)
  • Write a mock data server using nodeJS in 5 minutes
  • Develop a component library based on VUE from zero to one
  • Build a front-end team component system from 0 to 1 (Advanced Advanced Prerequisite)
  • Hand-write 8 common custom hooks in 10 minutes
  • Master Redux: Developing a Task Management platform (1)
  • Javascript Design Patterns front-end Engineers Need to Know in 15 minutes (with detailed mind maps and source code)
  • A picture shows you how to play vue-Cli3 quickly
  • “Front End Combat Summary” using postMessage to achieve pluggable cross-domain chatbot