title | type | order |
---|---|---|
Composants dynamiques et asynchrones |
guide |
105 |
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.
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 :
{% raw %}
Dont wait for the storm to pass, dance in the rain kick up litter decide to want nothing to do with my owner today demand to be let outside at once, and expect owner to wait for me as i think about it cat cat moo moo lick ears lick paws so make meme, make cute face but lick the other cats. Kitty poochy chase imaginary bugs, but stand in front of the computer screen. Sweet beast cat dog hate mouse eat string barf pillow no baths hate everything stare at guinea pigs. My left donut is missing, as is my right loved it, hated it, loved it, hated it scoot butt on the rug cat not kitten around
' }, { id: 2, title: 'Hipster Ipsum', content: 'Bushwick blue bottle scenester helvetica ugh, meh four loko. Put a bird on it lumbersexual franzen shabby chic, street art knausgaard trust fund shaman scenester live-edge mixtape taxidermy viral yuccie succulents. Keytar poke bicycle rights, crucifix street art neutra air plant PBR&B hoodie plaid venmo. Tilde swag art party fanny pack vinyl letterpress venmo jean shorts offal mumblecore. Vice blog gentrify mlkshk tattooed occupy snackwave, hoodie craft beer next level migas 8-bit chartreuse. Trust fund food truck drinking vinegar gochujang.
' }, { id: 3, title: 'Cupcake Ipsum', content: 'Icing dessert soufflé lollipop chocolate bar sweet tart cake chupa chups. Soufflé marzipan jelly beans croissant toffee marzipan cupcake icing fruitcake. Muffin cake pudding soufflé wafer jelly bear claw sesame snaps marshmallow. Marzipan soufflé croissant lemon drops gingerbread sugar plum lemon drops apple pie gummies. Sweet roll donut oat cake toffee cake. Liquorice candy macaroon toffee cookie marzipan.
' } ], selectedPost: null } }, template: '\- \
\
{{ post.title }}\
\
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 :
{% raw %}
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 `` 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.
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](browserify/browserify#58 (comment)) 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](vuejs#620), 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.
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.