Met behulp van Bereik Slots in Vue.js te Abstract Functionaliteit

0
15

Laten we beginnen met een korte introductie Vue.js slots concept. Slots zijn handig wanneer u wilt injecteren inhoud in een specifieke plaats van een onderdeel. Deze specifieke plaatsen, die u kunt definiëren zijn de zogenaamde slots.

Bijvoorbeeld, u wilt maken van een wrapper component die is ingericht in een specifieke wijze, maar je wilt in staat zijn om de inhoud te worden gegeven binnen de wrapper (is het misschien een string, een berekende waarde, of zelfs een andere component).

Er zijn drie soorten van slots:

  • standaard / naamloos slots: gebruikt wanneer u een enkel slot in een component. We creëren door het toevoegen van <sleuf> in het sjabloon waar we willen om te kunnen injecteren van onze content. Deze <sleuf> – tag zal worden vervangen door een content doorgegeven aan het onderdeel van de sjabloon.
  • de naam slots: gebruikt wanneer u meerdere slots in een component en we willen het injecteren van verschillende content op verschillende plaatsen (slots). We creëren door het toevoegen van <sleuf> met een attribuut naam (b.v. <slot name=”header”></slot>). Toen we maken onze component, wij bieden een slot content voor elk genoemde slot door het toevoegen van een slot attribuut met de sleuf naam.

<base-indeling>
<sjabloon slot=”header”>
<h1>Mijn awsome koptekst</h1>
</template>
<sjabloon slot=”footer”>
<p>Mijn awsome voettekst</p>
</template>
</base-indeling>

Door dat te doen, de <sleuf> tags in het onderdeel worden vervangen door de inhoud doorgegeven aan de component.

  • bereik slot: wanneer je een sjabloon in een slot om toegang te krijgen tot de gegevens van het kind component dat maakt de slot-inhoud. Dit is vooral handig wanneer u vrijheid in het maken van aangepaste sjablonen die gebruik maken van het kind component data-eigenschappen.

Real-World Voorbeeld: het Maken van een Google Map Loader component

Stel je voor een component die configureert en bereidt een externe API om te worden gebruikt in een ander component, maar is niet goed in combinatie met een specifieke sjabloon. Een dergelijke component kan dan worden hergebruikt in meerdere plaatsen rendering verschillende sjablonen, maar met dezelfde base object met een specifieke API.

Ik heb een component (GoogleMapLoader.vue) dat:

  1. initialiseert de Google Maps API
  2. maakt google en objecten
  3. bloot die objecten aan de ouder component waarin de GoogleMapLoader wordt gebruikt

Hieronder is een voorbeeld van hoe dit gerealiseerd kan worden. Wij analyseren de code stuk-voor-stuk en zien wat er daadwerkelijk gebeurt in de volgende paragraaf.

Laten we eerst vooropstellen onze GoogleMapLoader.vue sjabloon:

<sjabloon>
<div>
<div class=”google-map” data-google-kaart></div>
<sjabloon v-als=”Boolean(deze.google) && Boolean(deze.kaart)”>
<slot :google=”google” :kaart=”kaart” />
</template>
</div>
</template>

Nu, ons script dient te voldoen aan een aantal props aan de component die ons in staat stelt om de Google Maps API en Kaart object:

importeren GoogleMapsApiLoader van “google-maps-api-loader”;

export standaard {
rekwisieten: {
mapConfig: Object,
apiKey: String
},
gegevens() {
terug {
google: null,
kaart: null
};
},
async aangekoppeld is() {
const googleMapApi = wachten GoogleMapsApiLoader({
apiKey: dit.apiKey
});
deze.google = googleMapApi;
deze.initializeMap();
},
methoden: {
initializeMap() {
const mapContainer =.$el.querySelector(“[data-google-kaart]”);
deze.kaart = new.van google.kaarten.Kaart(mapContainer, dit.mapConfig);
}
}
};

Dit is slechts een onderdeel van een werkend voorbeeld. U kunt duiken in de diepere dit voorbeeld.

OK, nu hebben we onze use case opgezet, laten we gaan naar het breken van de code naar beneden om te ontdekken wat het doet.

1. Het maken van een component die wordt geïnitialiseerd onze kaart

In het sjabloon, maken we een container voor de kaart die worden gebruikt voor het monteren van de Kaart object gehaald uit de Google Maps API.

// GoogleMapLoader.vue
<sjabloon>
<div>
<div class=”google-map” data-google-kaart></div>
</div>
</template>

Naast onze script moet ontvangen rekwisieten van de ouder component die ons in staat stellen om de Kaart van Google. Deze rekwisieten bestaat uit:

  • mapConfig: Google Maps config object
  • apiKey: Onze persoonlijke api-sleutel nodig door Google Maps

// GoogleMapLoader.vue
importeren GoogleMapsApiLoader van “google-maps-api-loader”;

export standaard {
rekwisieten: {
mapConfig: Object,
apiKey: String
},

Vervolgens stellen we de initiële waarden van google en in kaart te null:

gegevens() {
terug {
google: null,
kaart: null
};
},

Op de gemonteerde haak, maken we een exemplaar van googleMapApi en de kaart-object. We moeten ook de waarden van google-kaart en de gemaakte exemplaren:

async aangekoppeld is() {
const googleMapApi = wachten GoogleMapsApiLoader({
apiKey: dit.apiKey
});
deze.google = googleMapApi;
deze.initializeMap();
},
methoden: {
initializeMap() {
const mapContainer =.$el.querySelector(“[data-google-kaart]”);
deze.kaart = new.van google.kaarten.Kaart(mapContainer, dit.mapConfig);
}
}
};

Zo ver, zo goed. Met dat alles klaar is, kunnen we verder gaan met het toevoegen van de andere objecten op de kaart (Markers, Polylijnen, enz.) en gebruik het als een gewone kaart component.

Maar, we willen gebruik maken van onze GoogleMapLoader component alleen een lader die voorbereidt op de kaart — we willen niet te maken.

Om dat te bereiken, moeten we toestaan dat de ouder component die gebruik maken van onze GoogleMapLoader om toegang te krijgen tot dit.google en deze.kaart die zijn ingesteld in de GoogleMapLoader component. Dat is waar binnen het bereik slots echt schitteren. Bereik slots stellen ons bloot te leggen de eigenschappen instellen in een onderliggende component naar het bovenliggende onderdeel. Het klinkt als een begin, maar geef me nog een minuut als we breken die verder naar beneden.

2. Maak component die gebruik maakt van onze initialiseren component

In het sjabloon, we maken van de GoogleMapLoader component en doorgeven rekwisieten die nodig zijn voor het initialiseren van de kaart.

// TravelMap.vue
<sjabloon>
<GoogleMapLoader
:mapConfig=”mapConfig”
apiKey=”yourApiKey”
/>
</template>

Ons script-tag ziet er als volgt uit:

importeren GoogleMapLoader uit “./GoogleMapLoader”;
importeren { mapSettings } van “@/constanten/mapSettings”;

export standaard {
onderdelen: {
GoogleMapLoader,
},
berekend: {
mapConfig() {
terug {
…mapSettings,
center: { lat: 0, lng: 0 }
};
},
}
};

Nog steeds geen bereik slots, dus laten we er één toevoegen.

3. Bloot google-kaart en eigenschappen van het bovenliggende onderdeel door het toevoegen van een bereik slot

Tot slot kunnen wij u een bereik slot die het werk doen en ons in staat stellen om toegang te krijgen tot de onderliggende component rekwisieten in het bovenliggende onderdeel. We doen dat door het toevoegen van de <sleuf> – tag in de onderliggende component en het passeren van de rekwisieten die we willen tonen (met een v-binden richtlijn of :propName steno). Het verschilt niet van het passeren van de rekwisieten in onderliggende component, maar doen het in de <sleuf> – tag zal het omkeren van de richting van de gegevensstroom.

// GoogleMapLoader.vue
<sjabloon>
<div>
<div class=”google-map” data-google-kaart></div>
<sjabloon v-als=”Boolean(deze.google) && Boolean(deze.kaart)”>
<slot
:google=”google”
:kaart=”kaart”
/>
</template>
</div>
</template>

Nu, als we in de sleuf van het kind component, we moeten ontvangen en te consumeren van de blootgestelde rekwisieten in het bovenliggende onderdeel.

4. Ontvangen blootgesteld rekwisieten in de ouder-onderdeel met behulp van de slot-scope-attribuut

Voor het ontvangen van de rekwisieten in de ouder-component, verklaren wij een template element en het gebruik van de slot-scope-attribuut. Dit kenmerk heeft toegang tot het object dragen alle rekwisieten blootgesteld van het kind component. We pakken het hele object, of we kunnen de structuur van dat object en wat we nodig hebben.

Laten we de structuur van dit ding te krijgen wat we nodig hebben.

// TravelMap.vue
<sjabloon>
<GoogleMapLoader
:mapConfig=”mapConfig”
apiKey=”yourApiKey”
>
<sjabloon slot-scope=”{ google map }”>
{{ kaart }}
{{ google }}
</template>
</GoogleMapLoader>
</template>

Hoewel de google-kaart en rekwisieten bestaat niet in de TravelMap omvang van de component heeft toegang tot hen en wij kunnen ze gebruiken in de sjabloon.

Ja, OK, maar waarom zou ik dat doen dat soort dingen? Wat is het nut van dit alles?

Blij dat je het vraagt! Bereik slots ons toelaten om een sjabloon aan het slot in plaats van een gerenderde element. Het heet een bereik slot want het zal de toegang tot bepaalde onderliggende component data-hoewel de sjabloon wordt weergegeven in het bovenliggende onderdeel van het toepassingsgebied. Dat geeft ons de vrijheid om te vullen van de sjabloon met de aangepaste inhoud van het bovenliggende onderdeel.

5. Maak fabriek onderdelen voor Markers en Polylijnen

Nu, als we onze kaart klaar is, maken we twee fabriek onderdelen die worden gebruikt om elementen toe te voegen aan de TravelMap.

// GoogleMapMarker.vue
importeren { POINT_MARKER_ICON_CONFIG } van “@/constanten/mapSettings”;

export standaard {
rekwisieten: {
google: {
type: Object,
nodig: true
},
kaart: {
type: Object,
nodig: true
},
markering: {
type: Object,
nodig: true
}
},
gemonteerd() {
nieuw dit.van google.kaarten.Marker({
positie:.marker.positie
markering: met deze.marker,
kaart: dit.kaart
pictogram: POINT_MARKER_ICON_CONFIG
});
},
};
// GoogleMapLine.vue
importeren { LINE_PATH_CONFIG } van “@/constanten/mapSettings”;

export standaard {
rekwisieten: {
google: {
type: Object,
nodig: true
},
kaart: {
type: Object,
nodig: true
},
pad: {
type: Array
nodig: true
}
},
gemonteerd() {
nieuw dit.van google.kaarten.Polylijn({
pad: dit.pad,
kaart: dit.kaart
…LINE_PATH_CONFIG
});
},
};

Beide van deze google krijgen die we gebruiken voor het uitpakken van het gewenste object (Marker of Polylijn) evenals kaart die het geeft als een verwijzing naar de kaart die we willen ons element.

Elke component verwacht ook een extra steun voor het maken van een bijbehorende element. In dit geval hebben we markering en het pad, respectievelijk.

Op de gemonteerde haak, maken we een element (Marker/Polylijn) en bevestig het op de kaart door het passeren van de kaart eigendom van het object constructor.

Er is nog één stap te gaan…

6. Elementen toevoegen aan de kaart

Laten we gebruik maken van onze fabriek componenten elementen toevoegen aan de kaart. We moeten weer de fabriek onderdeel en pas de google-kaart en objecten, zodat de gegevens stromen naar de juiste plek.

We moeten ook de gegevens te verstrekken, die nodig zijn door het element zelf. In ons geval is dat de marker object met de positie van de marker en de pad-object met Polylijn coördinaten.

Hier gaan we, de integratie van de gegevens wijst direct in de template:

// TravelMap.vue
<sjabloon>
<GoogleMapLoader
:mapConfig=”mapConfig”
apiKey=”yourApiKey”
>
<sjabloon slot-scope=”{ google map }”>
<GoogleMapMarker
v-for=”marker in markers”
:key=”marker.id”
:marker=”marker”
:google=”google”
:kaart=”kaart”
/>
<GoogleMapLine
v-for=”line in-lijnen”
:key=”line.id”
:pad.sync=”line.pad”
:google=”google”
:kaart=”kaart”
/>
</template>
</GoogleMapLoader>
</template>

Moeten We importeren de vereiste fabriek onderdelen in ons script en het instellen van de gegevens die worden doorgegeven aan de markeringen en de lijnen:

importeren { mapSettings } van “@/constanten/mapSettings”;

export standaard {
onderdelen: {
GoogleMapLoader,
GoogleMapMarker,
GoogleMapLine
},
gegevens() {
terug {
markeringen: [
{ id: “”, positie: { lat: 3, lng: 101 } },
{ id: “b”, positie: { lat: 5, lng: 99 } },
{ id: “c”, positie: { lat: 6, lng: 97 } }
],
lijnen: [
{ id: “1”, pad: [{ lat: 3, lng: 101 }, { lat: 5, lng: 99 }] },
{ id: “2”, pad: [{ lat: 5, lng: 99 }, { lat: 6, lng: 97 }] }
]
};
},
berekend: {
mapConfig() {
terug {
…mapSettings,
center: dit.kaartcentrum
};
},
kaartcentrum() {
retourneren.markeringen[1].positie;
}
}
};

En we zijn klaar!

Met al die stukjes en beetjes voltooid, nu kunnen we opnieuw gebruik maken van de GoogleMapLoader component als basis voor al onze kaarten door het passeren van verschillende sjablonen om elke een van hen. Stel je voor dat je nodig hebt voor het maken van een andere kaart met verschillende Markers of gewoon Markers zonder Polylijnen. Met behulp van een patroon van bereik slots, wordt het heel eenvoudig, want we moeten nu voorbij is verschillende inhoud aan de GoogleMapLoader component.

Dit patroon is niet strikt verbonden met Google Maps; het kan worden gebruikt met elke bibliotheek om de basis component en bloot de bibliotheek API die kunnen vervolgens worden gebruikt in het onderdeel dat opgeroepen de basis component.

Het is misschien verleidelijk om het creëren van een meer complexe of uitgebreide oplossing, maar dit wordt ons de abstractie die we nodig hebben en het wordt een zelfstandig onderdeel van onze codebase. Als we naar dat punt, dan is het misschien het overwegen waard extractie om een add-on.