Composants dynamiques et asynchrones

Cette page suppose que vous avez déjà lu les principes de base des composants. Lisez-les en premier si les composants sont quelque chose de nouveau pour vous.

keep-alive avec les composants dynamiques

Précédemment, nous avons utilisé l’attribut is pour basculer entre des composants dans une interface avec des onglets :

<component v-bind:is="composantOngletActuel"></component>

Toutefois, lors de la bascule d’un composant à l’autre, vous voudrez parfois maintenir leur état ou éviter de refaire leur rendu pour des raisons de performance. Par exemple, en détaillant un peu plus notre interface avec onglets :

Vous remarquerez que si vous sélectionnez un post, puis basculez sur l’onglet Archive, puis rebasculer à nouveau sur Posts, il n’affiche plus le post que vous avez initialement sélectionné. En effet, chaque fois que vous basculez vers un nouvel onglet, Vue crée une nouvelle instance du composantOngletActuel.

Recréer des composants dynamiques est d’habitude un comportement utile, mais dans ce cas précis, nous aimerions bien que ces instances de composants onglets soient mises en cache après qu’elles aient été créées pour la première fois. Pour résoudre ce problème, nous pouvons envelopper notre composant dynamique dans un élément <keep-alive> :

<!-- Les composants inactifs seront mis en cache ! -->
<keep-alive>
<component v-bind:is="composantOngletActuel"></component>
</keep-alive>

Observez le résultat ci-dessous :

Désormais, l’onglet Posts conserve son état (le post sélectionné) même lorsqu’il n’est pas dessiné. Consultez ce fiddle pour le code complet.

Notez que <keep-alive> requiert que tous les sous-composants aient un nom, soit via l’option name des composants, soit via une inscription locale/globale de ces composants.

Pour plus de détails sur <keep-alive>, consultez la référence API.

Composants asynchrones

Dans de grosses applications, nous pouvons avoir besoin de diviser l’application en morceaux plus petits et charger un composant depuis le serveur seulement lorsque celui-ci est requis. Pour rendre cela plus facile, Vue vous permet de définir un composant en tant que fonction usine qui va résoudre de façon asynchrone la définition de votre composant. Vue déclenchera la fonction usine seulement lorsque le rendu du composant est nécessaire, et mettra en cache le résultat pour les futurs nouveaux rendus. Par exemple :

Vue.component('exemple-async', function (resolve, reject) {
setTimeout(function () {
// Passe la définition du composant à la fonction de rappel `resolve`
resolve({
template: '<div>Je suis asynchrone !</div>'
})
}, 1000)
})

Comme vous pouvez le voir, la fonction usine reçoit en paramètre resolve, une fonction de rappel (callback) qui sera appelée lorsque vous aurez récupéré la définition du composant depuis le serveur. Vous pouvez également appeler reject(raison) pour indiquer que le chargement a échoué pour une certaine raison. Le setTimeout est là en guise de démonstration ; à vous de décider comment vous souhaitez récupérer le composant. Une approche recommandée est d’utiliser les composants asynchrones conjointement avec la fonctionnalité de découpage de code de webpack:

Vue.component('exemple-webpack-async', function (resolve) {
// Cette syntaxe spéciale `require` indique à webpack de
// diviser automatiquement votre code en sortie en paquets
// qui seront chargés via des requêtes AJAX.
require(['./mon-composant-async'], resolve)
})

Vous pouvez également retourner une Promise dans la fonction usine, ainsi avec webpack 2 et la syntaxe ES2015 vous pourrez écrire :

Vue.component(
'exemple-webpack-async',
// La fonction `import` retourne une `Promise`.
() => import('./mon-composant-async')
)

Quand vous utilisez l’inscription locale de composant, vous pouvez aussi fournir directement une fonction qui retourne une Promise :

new Vue({
// ...
components: {
'mon-composant': () => import('./mon-composant-async')
}
})

Si vous êtes un utilisateur de Browserify et souhaitez utiliser les composants asynchrones, son créateur a malheureusement été très clair sur le fait que le chargement asynchrone n’est pas quelque-chose que Browserify supportera un jour. Officiellement du moins. La communauté Browserify a trouvé quelques solutions de contournement, qui peuvent s’avérer utiles pour les applications complexes existantes. Pour tous les autres scénarios, nous recommandons d’utiliser webpack pour un support natif et de première classe de l’asynchrone.

Gérer l’état de chargement

Nouveauté de la 2.3.0+

La fabrique de composants asynchrones peut aussi retourner un objet avec le format suivant :

const AsyncComponent = () => ({
// Le composant à charger (doit être une `Promise`)
component: import('./MonComposant.vue'),
// Un composant à utiliser pendant que le composant asynchrone se charge
loading: LoadingComponent,
// Un composant d'erreur à utiliser au cas où le chargement échoue
error: ErrorComponent,
// Le délai à patienter avant d'afficher le composant de chargement. Par défaut : 200ms.
delay: 200,
// Le composant d'erreur sera affiché si un délai de timeout est fourni et dépassé.
// Par défaut: délai infini.
timeout: 3000
})

Notez que vous devez utiliser Vue Router en version 2.4.0+ si vous souhaitez utiliser la syntaxe ci-dessus pour des composants de routes.