
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.