
Les mixins Vue sont le moyen recommandé de partager des fonctionnalités communes entre les composants. Ils sont parfaitement bien jusqu'à ce que vous en utilisiez plus d'un. En effet, ils sont implicites par conception et polluent le contexte de votre composant. Essayons de résoudre ce problème en leur donnant autant d'explication que possible.
Objectif
Nous aimerions avoir un mixin global qui donne à n'importe quel composant un accessoire appelé types
et génère un tableau de classes CSS appelées mods
qui dérivent de baseClass
.
Compte tenu de ce balisage:
<SampleComponent :types="['active', 'block']"></SampleComponent>
Nous nous attendrions à avoir ceci (en supposant que notre baseClass
est sample-component
):
<div class="sample-component sample-component--active sample-component--block"></div>
Approche naïve
En lisant uniquement la documentation Vue, votre première pensée pourrait être d'utiliser simplement la fusion de propriétés intégrée et de fournir des mods
comme propriété calculée dans un composant souhaité.
// SampleComponent.vue <template> <div class="sample-component" :class="mods"><slot /></div> </template>
import bemMods from 'bemMods.js'; export default { name: 'SampleComponent', mixins: [ bemMods('sample-component') ] }
Cette approche souffre de nombreux problèmes:
- Code de chaudière dans chaque composant. (au moins dans une approche Vue)
- Dépendance d'un argument
baseClass
. - Aucune indication claire d'où vient la propriété des
mods
. - Les conflits de noms sont facilement possibles.
Nous essaierons de résoudre tous ces problèmes dans une prochaine étape.
Mixin avec une exportation explicite
Vue dispose d'un mécanisme d'injection de dépendances, appelé Inject \ Provider . Cela peut potentiellement résoudre notre problème avec un contexte polluant.
Dans un premier temps, passons d'un simple mixin à un plugin, qui accepte des options, que nous utiliserons plus tard pour éviter les conflits de noms.
Deuxièmement, nous pouvons également réutiliser le nom de notre composant comme baseClass
et ne pas l'inclure comme option personnalisée dans chaque composant.
Enfin, nous laisserons une option pour passer baseClass
comme argument de fonction au cas où la baseClass
notre composant ne correspondrait pas à son nom.
Nous sommes maintenant prêts à enregistrer notre plugin dans le monde entier.
import Vue from 'vue'; import bemMods from 'bemMods.js'; Vue.use(bemMods);
Nous pouvons également personnaliser la façon dont nos accessoires sont appelés, en fournissant un objet options.
import Vue from 'vue'; import bemMods from 'bemMods.js'; Vue.use(bemMods, { propName: 'modifiers', modsName: 'classes' });
Et voici à quoi ressemble notre composant après refactoring mixin:
<template> <div class="sample-component" :class="mods"><slot /></div> </template>
export default { name: 'SampleComponent',
Imaginons que notre composant n'a pas de name
ou qu'il ait une baseClass
différente de son nom:
<template> <div class="special-component" :class="mods('snowflake')"><slot /></div> </template>
export default { name: 'SpecialComponent', inject: ['mods'] }
Ou si nous voulons être prêts pour une refactorisation ou une suppression de plugin:
export default { name: 'SomeComponent', inject: {
Vous pouvez également utiliser Symbol
comme nom de mods pour éliminer complètement les conflits de noms, mais cela vous obligerait à inclure ce symbole dans chaque composant où vous souhaitez utiliser bemMods
.
Nous n'avons pas spécifié implicitement notre nom de prop, mais c'est une limitation de mixage de base, que nous avons essayé de surmonter avec un nom de prop personnalisé dans une configuration de plugin.
J'espère que cela vous a été utile et que vous avez trouvé une meilleure façon d'écrire des mixins pour Vue.