Learned Vue defineAsyncComponent Api, which taught me this knowledge?

Posted by PHP_PhREEEk on Mon, 17 Jan 2022 21:48:03 +0100

Author: Apoorv Tyagi
Translator: front end Xiaozhi
Source: dev

There are dreams and dry goods. Wechat search [Daqian world] pays attention to this bowl washing wisdom who is still washing dishes in the early morning.

This article GitHub https://github.com/qq449245884/xiaozhi It has been included. There are complete test sites, materials and my series of articles for the interview of front-line large factories.

Using the DefileAsyncComponent function of Vue3 allows us to lazy load components. In other words, we create an asynchronous component that will be loaded only when needed.

This is a good way to improve the initial page loading, because our application will load into smaller blocks instead of having to load each component when the page loads.

In this article, we will learn all about defining asynccomponent and an example of lazy loading pop-up window.

What is defineAsyncComponent?

const AsyncComp = defineAsyncComponent(
  () =>
    new Promise((resolve, reject) => {
      resolve({
        template: '<div>I am async!</div>'
      })
    })
)

defineAsyncComponent can accept a factory function that returns promise. Promise's resolve callback should be called after the server returns the component definition. You can also call reason to indicate that the load failed.

defineAsyncComponent can be imported from vue and used:

import { defineAsyncComponent } from "vue" 

// simple usage 
const LoginPopup = defineAsyncComponent(() => import("./components/LoginPopup.vue"))

This is the simplest method of defining asynccomponent. For high-level usage, defineAsyncComponent can accept an object:

const AsyncPopup = defineAsyncComponent({ 
  loader: () => import("./LoginPopup.vue"),
   // Components to use when loading asynchronous components
  loadingComponent: LoadingComponent,
   // Components to use when loading fails
  errorComponent: ErrorComponent, 
  // Delay before displaying loadingComponent | default value: 200 (unit: ms)
  delay: 1000, 
  // If timeout is provided and the time to load the component exceeds the set value, an error component will be displayed
  // Default value: Infinity (i.e. never timeout, unit: ms)
  timeout: 3000 
})

The foundation has been introduced. Then, let's take an example.

Loading Popup components asynchronously using defineAsyncComponent

In this example, we will use a login pop-up triggered by clicking a button.

We don't need our application to load this component every time it is loaded, because it is only needed when the user performs a specific action.

The following is the implementation of the login component:

// LoginPopup.vue
<template>
   <div class="popup">
       <div class="content">
           <h4> Login to your account </h4>
           <input type="text" placeholder="Email" />
           <input type="password" placeholder="Password" />
           <button> Log in </button>
       </div>
   </div>
</template>

<script>
</script>

<style scoped>
.popup {
    position: fixed;
    width: 100%;
    top: ; 
    left: ;
    height: 100%;
    background-color: rgba(, , , 0.2);
    display: flex;
    justify-content: center;
    align-items: center;
}
.content {
   min-width: 200px;
   width: 30%;
   background: #fff;
   height: 200px;
   padding: 10px;
   border-radius: 5px;
}
input[type="text"], input[type="password"] {
    border: ;
    outline: ;
    border-bottom: 1px solid #eee;
    width: 80%;
    margin:  auto;
    font-size: 0.5em;
}
button {
   border: ;
   margin-top: 50px;
   background-color:#8e44ad;
   color: #fff;
   padding: 5px 10px;
   font-size: 0.5em;
}
</style>

Import it in other components:

<template>
  <button @click="show = true"> Login </button>
  <login-popup v-if="show" />
</template>

<script>
import LoginPopup from './components/LoginPopup.vue'
export default {
  components: { LoginPopup },
  data() {
    return {
      show: false
    }
  }
}
</script>

We can use define asynccomponent and load it only when needed (use v-if to switch when the button is clicked).

<!-- Use defineAsyncComponent  -->
<template>
  <button @click="show = true"> Login </button>
  <login-popup v-if="show" />
</template>

<script>
import { defineAsyncComponent } from 'vue'
export default {
  components: { 
    "LoginPopup" : defineAsyncComponent(() => import('./components/LoginPopup.vue'))
  },
  data() {
    return {
      show: false
    }
  }
}
</script>

This usage looks similar to the one above. Don't worry. Let's F12 open the console.

If we don't use defineasync component, once our page loads, we will see our application get loginpopup. Com from the server vue. Although the performance problem is not so serious in this example, if we have dozens of components to do so, the performance will be affected more or less.

However, if we use defineAsyncComponent to view the same tag, we will notice that when our page loads, loginpopup Vue is not available because it has not been loaded.

However, if we switch the button, we can see it:

This helps us achieve the best performance. We just want to load the required components when our page is initially loaded. Conditional rendering components are often unnecessary when our page is loaded, so why let our application load them?

How is it used with asynchronous setup methods?

Whether we use defineAsyncComponent to load asynchronously or not, any component with asynchronous setup method must be wrapped with < suspend >.

In short, creating an asynchronous setup function is one of our options, allowing our components to wait for some API calls or other asynchronous operations before rendering.

The following is a component with asynchronous setup, which uses setTimeout() to simulate API calls

<template>
   <div class="popup">
       <div class="content">
            <p> Loaded API: {{ article }} </p>
           <h4> Login to your account </h4>
           <input type="text" placeholder="Email" />
           <input type="password" placeholder="Password" />
           <button> Log in </button>
       </div>
   </div>
</template>

<script>
const getArticleInfo = async () => {
     // wait 3 seconds to mimic API call
    await new Promise(resolve => setTimeout(resolve, 1000));
    const article = {
        title: 'My Vue 3 Article',
        author: 'Matt Maribojoc'
    }
    return article
}
export default {
    async setup() {
        const article = await getArticleInfo()
        console.log(article)
        return {
            article
        }
    }
}
</script>

We can import it into the component with or without defineAsyncComponent:

import LoginPopup from './components/LoginPopup.vue'

// OR 

const LoginPopup = defineAsyncComponent(() => import("./components/LoginPopup.vue"))

But if we want it to render in our template, we need to package it in a suspend element. This will wait for our setup to parse before trying to render our components.

A good feature of suspend is that we can use slots and templates to display fallback content. The fallback will be displayed until the setup function resolves and our component is ready to render. Note that v-if has been moved from the component itself to our suspend component, so all fallback content will be displayed.

<template>
  <button @click="show = true"> Login </button>
  <Suspense v-if="show">
    <template #default>
      <login-popup  />
    </template>
    <template #fallback>
      <p> Loading... </p>
    </template>
  </Suspense>
</template>

The following is the running result. You will see "Loading..." and then render the component after 3 seconds (the hard coded value of setTimeout).

By default, all components we define using defineAsyncComponent are suspendable.

This means that if there is a suspension in the parent chain of a component, it will be regarded as an asynchronous dependency of the suspension. The load, error, delay, and timeout options for our components will be ignored and handled by suspend.

summary

Defining asynccomponent is useful when building large projects that package many components. When we use lazy loading components, we can load pages faster, improve the user experience, and finally improve the retention rate and conversion rate of applications.

I'd like to know what you think of this feature. If you have already used it in your application, remember to leave a message and share it below.

I'm Xiao Zhi. What are you going to do today~

The bugs that may exist after code deployment cannot be known in real time. Afterwards, in order to solve these bugs, we spent a lot of time on log debugging. By the way, we recommend a useful BUG monitoring tool Fundebug.

Original text: https://learnvue.co/2021/06/lazy-load-components-in-vue-with-defineasynccomponent/

communication

There are dreams and dry goods. Wechat search [Daqian world] pays attention to this bowl washing wisdom who is still washing dishes in the early morning.

This article GitHub https://github.com/qq449245884/xiaozhi It has been included. There are complete test sites, materials and my series of articles for the interview of front-line large factories.

Topics: Front-end TypeScript Vue