9

I'm using laravel 5.4 and vue 2 and I want to load a component as async using a button. My Vue js components are separate: example.vue and test.vue and I load them as an html tag.

This is my app.js:

import './bootstrap';
import example from './components/Example.vue';

Vue.component('example', example);

const app = new Vue({
el: '#app'
});

This is the place to show components

    <How can i use Async components?div id="app">
         <example2></example2> 
    </div>

How can I use Async components?


No, I think you don't understand me. It's my component registration

import './bootstrap';
import example from './components/Example.vue';

Vue.component('example', example);

Vue.component('example2', function (resolve) {

require(['./components/Example2.vue'],resolve)

})


const app = new Vue({
el: '#app'
});

and in require , it default resolved (as showing) I don't know how should I pass the resolve and reject keys to this method in my page when I call the component.

Ann Kilzer
  • 1,266
  • 3
  • 16
  • 39
K1-Aria
  • 1,093
  • 4
  • 21
  • 34
  • 2
    https://vuejs.org/v2/guide/components.html#Async-Components – Egor Stambakio Apr 19 '17 at 14:43
  • Best way to loading components asynchronously is using lazy loading like the following ``` components: { ComponetName: () => import ('./component.vue') } ``` read more about options here: https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components – Naren Nov 30 '19 at 20:57

5 Answers5

10

You can use async component in vue 2 with a styling way. Proper using async component can reduce your project loading time. You can use async component as like:

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router ({
routes: [
  {
    path: '/',
    name:'LandingPage'
    component: () => import('@/containers/LandingPage.vue')
  },
  {
    path: '/login',
    name:'LoginPage'
    component: () => import('@/containers/LoginPage.vue')
  }
]
})

This structure looks better for component loading inside the template:

new Vue ({
  el: 'app',
    components: {
      AsyncComponent: () => import ('./AsyncComponent.vue')
    }
})

You can check out: www.bdtunnel.com for more information.

Sukanta Bala
  • 871
  • 1
  • 9
  • 19
5

According to documentation on VueJs you can define asynchronous components like this since version 2.3

const AsyncComp = () => ({
  // The component to load. Should be a Promise
  component: import('./MyComp.vue'),
  // A component to use while the async component is loading
  loading: LoadingComp,
  // A component to use if the load fails
  error: ErrorComp,
  // Delay before showing the loading component. Default: 200ms.
  delay: 200,
  // The error component will be displayed if a timeout is
  // provided and exceeded. Default: Infinity.
  timeout: 3000
})

You can use this in conjunction with built in component to load your components dynamically.

EDIT: An updated link to mentioned documentation.

tony19
  • 125,647
  • 18
  • 229
  • 307
Gorky
  • 1,393
  • 19
  • 21
4

For async components in Vue.js, the resolve argument is the function which is called upon success of the async call, so your require() call needs to be inside the called resolve function. You just need to remove the brackets in your require() call and format that line as follows:

resolve(require('./components/Example2.vue'))

In the example below, we're using a basic setTimeout() to emulate the async call. The resolve function will be called after 5 seconds and will load the Example2 component into the app.

In order to show/hide the Example2 component via a button click, you have to add a reactive data property in the data() function. Then, if you take a look at App.vue's template, we're using the v-if (https://v2.vuejs.org/v2/guide/conditional.html#v-if) directive to add/remove the Example2 component to/from the virtual DOM. You could very easily us the v-show (https://v2.vuejs.org/v2/guide/conditional.html#v-show) directive here as well, although the component would stick around and just be hidden. You can read more about v-if vs v-show here: https://v2.vuejs.org/v2/guide/conditional.html#v-if-vs-v-show. This is a very common paradigm for hiding and showing modals in an app -- here's an example that shows this in action quite well: https://v2.vuejs.org/v2/examples/modal.html

main.js

import Vue from 'vue'
import App from './components/App.vue'

Vue.component('example2', function(resolve, reject) {
  setTimeout(function() {
    resolve(require('./components/Example2.vue'))
  }, 5000)
})

const app = new Vue({
  el: '#app',
  render: h => h(App)
})

Example2.vue

<template>
  <div>
    <div>Hello example 2!</div>
  </div>
</template>      

App.vue

<template>
  <div id="app">
    <button type="button" @click="onButtonClick">Click me to add the example2 component</button>
    <example2 v-if="show_example2"></example2>
  </div>
</template>

<script>
  export default {
    name: 'app',
    data() {
      return {
        show_example2: false
      }
    },
    methods: {
      onButtonClick() {
        this.show_example2: true
      }
    }
  }
</script>
tony19
  • 125,647
  • 18
  • 229
  • 307
dzwillia
  • 79
  • 4
  • every time i use this : , the component will appear. i mean how can i load component using a button??? – K1-Aria Apr 20 '17 at 10:10
  • Ah, gotcha. What you'd want to do is add a reactive data property in your App.vue file in order to show the component on button click. I'll edit the example above to show you how to do that. – dzwillia Apr 20 '17 at 14:18
1

One way I've done this sort of thing is to create your example2 component with the following setup:

<template>
  <div>
    <div v-if="inited">
      <div>{{foo}}</div>
      <div>{{bar}}</div>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        foo: '',
        bar: '',
        inited: false
      }
    },
    mounted() {
      var me = this
      axios.get('/my/ajax/call').then(function(response) {
        me.foo = response.data.foo
        me.bar = response.data.bar
        me.inited = true
      })
    }
  }
</script>

Basically, anytime the component is mounted, it'll render with empty information until the AJAX call completes and then the reactive data will be updated and Vue will auto-update the reactive data elements. If you have other markup or things in the template you don't want to be visible, you can always create an inited: false data property and set it to true in the AJAX callback and then use either the :v-if="inited" or :v-show="inited" directives on a wrapper div to hide the component's contents until the AJAX call returns.

dzwillia
  • 79
  • 4
1

Vue 3 - Breaking Changes

async components now require defineAsyncComponent helper method:

// vue 2.x
const asyncPage = () => import('./NextPage.vue')

// vue 3.x
const asyncPage = defineAsyncComponent(() => import('./NextPage.vue'))

Another breaking change is that component option is renamed to loader when definig additional options:

const asyncPageWithOptions = defineAsyncComponent({
  loader: () => import('./NextPage.vue'),
  delay: 200,
  timeout: 3000,
  error: ErrorComponent,
  loading: LoadingComponent
})

Docs: https://v3-migration.vuejs.org/breaking-changes/async-components.html#_3-x-syntax

tony19
  • 125,647
  • 18
  • 229
  • 307
t_dom93
  • 10,226
  • 1
  • 52
  • 38