8

I'm using Laravel 5.4 and Vue.js 2. 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 defaults to resolved (as showing). I don't know how I should pass the resolve and reject keys to this method in my page when I call the component.

2

5 Answers 5

10

You can use async components in Vue.js 2 with a styling way. Proper using async components can reduce your project loading time.

You can use an 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.

Sign up to request clarification or add additional context in comments.

Comments

5

According to the documentation on Vue.js, you have been able to 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: 200 ms.
  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 components to load your components dynamically.

An updated link to mentioned documentation.

1 Comment

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>

2 Comments

every time i use this : <example2></example2> , the component will appear. i mean how can i load component using a button???
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.
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.

Comments

1

Vue.js 3 - Breaking Changes

Async components now require the defineAsyncComponent helper method:

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

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

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

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

Documentation: Async Components, 3.x Syntax

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.