
Vue-Mixins sind die empfohlene Methode, um gemeinsame Funktionen zwischen Komponenten zu teilen. Sie sind vollkommen in Ordnung, bis Sie mehr als eine für sie verwenden. Dies liegt daran, dass sie vom Design her implizit sind und den Kontext Ihrer Komponente verschmutzen. Versuchen wir, dies zu beheben, indem wir ihnen so viel Aussagekraft wie möglich geben.
Ziel
Wir möchten ein globales Mixin, das jeder Komponente eine Requisite namens types gibt und ein Array von CSS-Klassen namens mods ausgibt, die von baseClass .
Angesichts dieses Aufschlags:
<SampleComponent :types="['active', 'block']"></SampleComponent>
Wir würden dies erwarten (vorausgesetzt, unsere baseClass ist eine sample-component ):
<div class="sample-component sample-component--active sample-component--block"></div>
Naiver Ansatz
Wenn Sie nur die Vue-Dokumentation lesen, besteht Ihr erster Gedanke möglicherweise darin, nur die integrierte Zusammenführung von Eigenschaften zu verwenden und mods als berechnete Eigenschaft in einer gewünschten Komponente bereitzustellen.
// 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') ] }
Dieser Ansatz weist viele Probleme auf:
- Boilerplate-Code in jeder Komponente. (zumindest in einem Vue-Ansatz)
- Abhängigkeit von einem
baseClass Argument. - Keine eindeutige Angabe, woher die
mods Eigenschaft stammt. - Namenskonflikte sind leicht möglich.
Wir werden versuchen, all diese Probleme in einem nächsten Schritt zu beheben.
Mischen Sie mit einem expliziten Export
Vue verfügt über einen Abhängigkeitsinjektionsmechanismus namens Inject \ Provide . Es kann möglicherweise unser Problem mit dem umweltschädlichen Kontext lösen.
Wechseln wir zunächst von einem einfachen Mixin zu einem Plugin, das Optionen akzeptiert, die wir später verwenden, um Namenskonflikte zu vermeiden.
Zweitens können wir den Namen unserer Komponente auch als baseClass und diesen nicht als benutzerdefinierte Option in jede einzelne Komponente aufnehmen.
Und schließlich lassen wir eine Option, um baseClass als Funktionsargument zu übergeben, baseClass die baseClass unserer Komponente nicht mit ihrem Namen übereinstimmt.
Wir sind jetzt bereit, unser Plugin weltweit zu registrieren.
import Vue from 'vue'; import bemMods from 'bemMods.js'; Vue.use(bemMods);
Wir können auch anpassen, wie unsere Requisiten aufgerufen werden, indem wir ein Optionsobjekt bereitstellen.
import Vue from 'vue'; import bemMods from 'bemMods.js'; Vue.use(bemMods, { propName: 'modifiers', modsName: 'classes' });
Und so sieht unsere Komponente nach dem Mixin-Refactoring aus:
<template> <div class="sample-component" :class="mods"><slot /></div> </template>
export default { name: 'SampleComponent',
Stellen wir uns vor, unsere Komponente hat keinen name oder eine andere baseClass als der Name:
<template> <div class="special-component" :class="mods('snowflake')"><slot /></div> </template>
export default { name: 'SpecialComponent', inject: ['mods'] }
Oder wenn wir für ein Refactoring oder das Entfernen von Plugins bereit sein möchten:
export default { name: 'SomeComponent', inject: {
Sie können Symbol als Mods-Namen verwenden, um Namenskonflikte vollständig zu beseitigen. bemMods müssten Sie dieses Symbol jedoch in jede einzelne Komponente aufnehmen, in der Sie bemMods verwenden bemMods .
Wir haben unseren Requisitennamen nicht implizit angegeben, aber dies ist eine zentrale Mixin-Einschränkung, die wir mit einem benutzerdefinierten Requisitennamen in einer Plugin-Konfiguration zu überwinden versucht haben.
Ich hoffe, das war hilfreich für Sie und Sie haben eine bessere Möglichkeit gefunden, Mixins für Vue zu schreiben.