This is the third day of my participation in the First Challenge 2022

Hello everyone, I am a bowl week, a front end that does not want to be drunk (inrolled). If I am lucky enough to write an article that you like, I am very lucky

Writing in the front

When our project reaches a certain size, for some components we don’t want to load them all at first, we want to load them as needed; The goal is to improve the user experience.

To do this, Vue3 provides us with a method called defineAsyncComponent. This method can pass two types of arguments, function type and object type, which we’ll look at separately.

Pass the factory function as a parameter

The defineAsyncComponent method is a basic usage that accepts a factory function that must return a Promise. The Promise’s resolve should return a component.

Here we take the Vue Cli created project as an example. Here I have made a slight modification to split the header image into a component as follows:

<template>
  <logo-img />
  <hello-world msg="Welcome to Your Vue.js App" />
</template>

<script setup>
import LogoImg from './components/LogoImg.vue'
import HelloWorld from './components/HelloWorld.vue'
</script>
Copy the code

Now let’s change the

component to an asynchronous component in the following code:

<template>
  <logo-img />
  <hello-world msg="Welcome to Your Vue.js App" />
</template>

<script setup>
import { defineAsyncComponent } from 'vue'
import LogoImg from './components/LogoImg.vue'

//
const HelloWorld = defineAsyncComponent(() = >
  import('./components/HelloWorld.vue'),</script>
Copy the code

Here’s an example of deferring import execution to see the effect:

<script setup>
import { defineAsyncComponent } from 'vue'
import LogoImg from './components/LogoImg.vue'

// Define a function that takes time to execute, with t representing the delay and callback representing the function that needs to be executed, optionally
const time = (t, callback = () => {}) = > {
  return new Promise(resolve= > {
    setTimeout(() = > {
      callback()
      resolve()
    }, t)
  })
}
// Define the asynchronous component, written here to see the effect
const HelloWorld = defineAsyncComponent(() = > {
  return new Promise((resolve, reject) = > {
    ;(async function () {
      try {
        await time(2000)
        const res = await import('./components/HelloWorld.vue')
        resolve(res)
      } catch (error) {
        reject(error)
      }
    })()
  })
})
</script>

Copy the code

The code run result is as follows:

The

component is loaded after 2s.

Pass the object type as a parameter

The defineAsyncComponent method can also take an object with the following parameters:

  • loader: same as factory function;
  • loadingComponent: components displayed when loading asynchronous components;
  • errorComponent: components displayed when loading components fails;
  • delay: displayloadingComponentThe previous delay time, in milliseconds, defaults to 200 milliseconds.
  • timeout: If providedtimeout, and the loading time of the component exceeds the set value, the error component is displayed. The default value isInfinity(in milliseconds);
  • suspensible: Asynchronous components can exit<Suspense>Control, and always control your own loading state. Please refer toThe document;
  • onError: a function that takes four arguments, respectivelyerror,retry,failandattemptsThe four parameters are the error object, the function that was reloaded, the function that the loader ended, and the number of retries that have been made.

The following code shows the use of the object type argument to the defineAsyncComponent method:

<template>
  <logo-img />
  <hello-world msg="Welcome to Your Vue.js App" />
</template>

<script setup>
import { defineAsyncComponent } from 'vue'
import LogoImg from './components/LogoImg.vue'
import LoadingComponent from './components/loading.vue'
import ErrorComponent from './components/error.vue'

// Define a function that takes time to execute, with t representing the delay and callback representing the function that needs to be executed, optionally
const time = (t, callback = () => {}) = > {
  return new Promise(resolve= > {
    setTimeout(() = > {
      callback()
      resolve()
    }, t)
  })
}
// Record the loading times
let count = 0
const HelloWorld = defineAsyncComponent({
  // Factory function
  loader: () = > {
    return new Promise((resolve, reject) = > {
      ;(async function () {
        await time(300)
        const res = await import('./components/HelloWorld.vue')
        if (++count < 3) {
          // Failed to load the manual Settings for the first two loads
          reject(res)
        } else {
          // More than 3 successes
          resolve(res)
        }
      })()
    })
  },
  loadingComponent: LoadingComponent,
  errorComponent: ErrorComponent,
  delay: 0.timeout: 1000.suspensible: false.onError(error, retry, fail, attempts) {
    // Note that retry/fail is like promise's resolve/reject:
    // One of these must be called to continue error handling.
    if (attempts < 3) {
      // Retry the request when an error occurs, up to three times
      console.log(attempts)
      retry()
    } else {
      fail()
    }
  },
})
</script>

Copy the code

In the above code, the first two attempts to load the component will fail, and only the third attempt will succeed. The code runs as follows:

The ErrorComponent is displayed if the load fails.

Write in the last

That’s all there is to say about asynchronous components in Vue3, but basically just a use of defineAsyncComponentAPI.