Ved hjelp Omfattet Spor i Vue.js til Abstrakt Funksjonalitet

0
31

La oss starte med en kort introduksjon til Vue.js spilleautomater konsept. Plasser er nyttig når du ønsker å injisere innhold i et bestemt sted til en komponent. De bestemte steder som du kan definere kalles slots.

For eksempel, ønsker du å lage en wrapper komponent som er utformet på en bestemt måte, men du vil være i stand til å passere noe innhold i å bli fremstilt inne som wrapper (det kan være en streng, en beregnet verdi, eller til og med en annen komponent).

Det er tre typer spor:

  • standard / navnløse slots: brukes når du har en enkel spilleautomat i en komponent. Vi skaper dem ved å legge til <slot> i malen der vi ønsker å være i stand til å injisere vårt innhold. Denne <slot> – taggen vil bli erstattet med noe innhold som sendes til komponent i malen.
  • oppkalt slots: brukes når du har flere spilleautomater i en komponent, og vi ønsker å injisere forskjellig innhold i forskjellige steder (slots). Vi skaper de ved å legge til <slot> med et navn attributt (f.eks. <slot name=”header”></slot>). Så når vi gjengi våre komponent, gir vi en spilleautomat innhold for hver navngitt spor ved å legge til en spilleautomat attributt med spilleautomat navn.

<base-oppsett>
<slot mal=”header”>
<h1>Mitt awsome overskriften</h1>
</template>
<slot mal=”footer”>
<p>Mitt awsome bunntekst</p>
</template>
</base-oppsett>

Ved å gjøre det, <slot> – tag-er i komponenten vil bli erstattet av innhold sendt til komponenten.

  • omfattet slot: brukes når du ønsker en mal inne i en slot for å få tilgang til data fra barnet komponent som gjør spilleautomat innhold. Dette er spesielt nyttig når du trenger frihet i å lage egendefinerte maler som bruker barnet komponent data egenskaper.

Real-World Eksempel: Opprette en Google Map Loader komponent

Tenk deg en komponent som konfigurerer og setter opp en ekstern API for å bli brukt i en annen komponent, men er ikke hører sammen med noen bestemt mal. En slik komponent kan da gjenbrukes på flere steder gjengivelse av forskjellige maler, men med samme base-objekt med spesifikke API.

Jeg har opprettet en komponent (GoogleMapLoader.vue) at:

  1. initialiserer Google Maps API
  2. skaper google og kart objekter
  3. utsetter disse objektene til den overordnede komponent som brukes GoogleMapLoader

Nedenfor er et eksempel på hvordan dette kan oppnås. Vi vil analysere koden bit-for-bit og se hva som faktisk skjer i neste avsnitt.

La oss først konstatere våre GoogleMapLoader.vue mal:

<mal>
<div>
<div class=”google-kart” data-google-kart></div>
<mal v-hvis=”Boolean(denne.google) && Boolske(denne.kart)”>
<slot :google=”google” :map=”kart” />
</template>
</div>
</template>

Nå, vår script må passere noen rekvisitter til den komponent som gjør det mulig for oss å angi Google Maps API og objektet:

import GoogleMapsApiLoader fra “google-maps-api-loader”;

eksport standard {
rekvisittar: {
mapConfig: Objekt,
apiKey: String
},
data() {
tilbake {
google: null,
kart: null
};
},
asynkron montert() {
const googleMapApi = venter GoogleMapsApiLoader({
apiKey: dette.apiKey
});
dette.google = googleMapApi;
dette.initializeMap();
},
metoder: {
initializeMap() {
const mapContainer = dette.$el.querySelector(“[data-google-kart]”);
dette.kart = new dette.google.kart.Kart(mapContainer dette.mapConfig);
}
}
};

Dette er bare en del av en fungerende eksempel. Du kan dykke ned i dypere dette eksemplet.

OK, nå som vi har i vår bruk tilfellet satt opp, la oss gå inn å bryte koden ned for å utforske hva det gjør.

1. Opprette en komponent som initierer våre kart

I malen, kan vi lage en beholder for kart som vil bli brukt til å feste objektet hentet fra Google Maps API.

// GoogleMapLoader.vue
<mal>
<div>
<div class=”google-kart” data-google-kart></div>
</div>
</template>

Neste opp, skriptet må få rekvisitter fra den overordnede komponent som vil tillate oss å sette en Google-Kartet. De propper består av:

  • mapConfig: Google Maps-config-objekt
  • apiKey: Våre personlige api-nøkkel som kreves av Google Maps

// GoogleMapLoader.vue
import GoogleMapsApiLoader fra “google-maps-api-loader”;

eksport standard {
rekvisittar: {
mapConfig: Objekt,
apiKey: String
},

Så, vi sette de opprinnelige verdiene av google og kart til null:

data() {
tilbake {
google: null,
kart: null
};
},

På den montert krok, vi oppretter en forekomst av googleMapApi og objektet fra det. Vi trenger også å angi verdier av google og kart til laget tilfeller:

asynkron montert() {
const googleMapApi = venter GoogleMapsApiLoader({
apiKey: dette.apiKey
});
dette.google = googleMapApi;
dette.initializeMap();
},
metoder: {
initializeMap() {
const mapContainer = dette.$el.querySelector(“[data-google-kart]”);
dette.kart = new dette.google.kart.Kart(mapContainer dette.mapConfig);
}
}
};

Så langt, så bra. Med alt som er gjort, vi kunne fortsette med å legge til andre objekter til kart (Markører, Polylinjer, etc.) og bruk det som en vanlig kart komponent.

Men, vi ønsker å bruke vår GoogleMapLoader komponenten bare som en hjullaster som forbereder seg på kartet — vi ønsker ikke å gjøre noe på det.

For å oppnå det, må vi tillate den overordnede komponent som vil bruke våre GoogleMapLoader å få tilgang til denne.google og dette.kartet som er satt inni GoogleMapLoader komponent. Det er der omfattet spilleautomater virkelig skinner. Omfattet slots tillater oss å avdekke egenskaper sett i et barn-komponenten til den overordnede komponent. Det kan høres ut som en begynnelse, men bær over med meg ett minutt som vi bryter det ned ytterligere.

2. Opprette komponent som bruker våre initializer komponent

I malen, vi gjengi GoogleMapLoader komponent og passere rekvisitter som er nødvendige for å initialisere kartet.

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

Vår script-taggen bør se ut som dette:

import GoogleMapLoader fra “./GoogleMapLoader”;
import { mapSettings } fra “@/konstanter/mapSettings”;

eksport standard {
komponenter: {
GoogleMapLoader,
},
beregnet: {
mapConfig() {
tilbake {
…mapSettings,
center: { lat: 0, lng: 0 }
};
},
}
};

Fortsatt ingen omfattet spor, så la oss legge til en.

3. Utsett google og kart egenskaper til den overordnede komponent ved å legge til en omfattet slot

Endelig kan vi legge til en omfattet slot som vil gjøre jobben, og gi oss mulighet til å få tilgang barnet komponent rekvisitter i den overordnede komponent. Vi gjør det ved å legge til <slot> – tag i barn komponent og passerer rekvisitter som vi ønsker å eksponere (ved hjelp av v-bind direktiv eller :propName stenografi). Det skiller seg ikke fra å sende rekvisitter ned til barnet komponent, men å gjøre det i <slot> – tag-en omvendt retning av data flyt.

// GoogleMapLoader.vue
<mal>
<div>
<div class=”google-kart” data-google-kart></div>
<mal v-hvis=”Boolean(denne.google) && Boolske(denne.kart)”>
<slot
:google=”google”
:map=”kart”
/>
</template>
</div>
</template>

Nå, når vi har sporet i barnet komponent, må vi mottar og bruker utsatt rekvisitter i den overordnede komponent.

4. Motta utsatt rekvisitter i den overordnede komponent ved hjelp av slot-omfang attributt

For å få rekvisitter i den overordnede komponent, vi erklærer en mal element og bruke spilleautomat-scope-attributtet. Denne egenskapen har tilgang til objektet bærer alle rekvisitter utsatt fra barnet komponent. Vi kan ta hele objektet, eller vi kan de-struktur som objekt og bare det vi trenger.

La oss de-struktur denne saken for å få det vi trenger.

// TravelMap.vue
<mal>
<GoogleMapLoader
:mapConfig=”mapConfig”
apiKey=”yourApiKey”
>
<slot mal-scope=”{ google, kart }”>
{{ kart }}
{{ google }}
</template>
</GoogleMapLoader>
</template>

Selv om google og kart rekvisitter ikke eksisterer i TravelMap omfang, den komponenten som har tilgang til dem, og vi kan bruke dem i malen.

Ja, OK, men hvorfor skulle jeg gjøre ting som det? Hva er vitsen med alt dette?

Glad du spurte! Omfattet slots tillater oss å passere en mal til sporet i stedet for en gjengis element. Det kalles en omfattet slot fordi det vil ha tilgang til enkelte barn komponent data, selv om malen er gjengitt i den overordnede komponent omfang. Det gir oss en frihet til å fylle ut malen med tilpasset innhold fra den overordnede komponent.

5. Opprette fabrikken komponenter for Markører og Polylinjer

Nå, når vi har våre kart klar, og vi vil opprette to factory komponenter som skal brukes til å legge til elementer til TravelMap.

// GoogleMapMarker.vue
import { POINT_MARKER_ICON_CONFIG } fra “@/konstanter/mapSettings”;

eksport standard {
rekvisittar: {
google: {
type: Object,
nødvendig: true
},
kart: {
type: Object,
nødvendig: true
},
markør: {
type: Object,
nødvendig: true
}
},
montert() {
nytt dette.google.kart.Markør({
posisjon: dette.markør.posisjon
markør: med dette.markør,
kart: dette.kart,
ikon: POINT_MARKER_ICON_CONFIG
});
},
};
// GoogleMapLine.vue
import { LINE_PATH_CONFIG } fra “@/konstanter/mapSettings”;

eksport standard {
rekvisittar: {
google: {
type: Object,
nødvendig: true
},
kart: {
type: Object,
nødvendig: true
},
bane: {
type: Matrise,
nødvendig: true
}
},
montert() {
nytt dette.google.kart.Polylinje({
bane: dette.vei,
kart: dette.kart,
…LINE_PATH_CONFIG
});
},
};

Begge disse mottar google som vi bruker til å trekke ut de nødvendige objekt (Markør eller Polylinje) samt kart som gir en referanse til kartet som vi ønsker å plassere vårt rette element.

Hver komponent forventer også en ekstra støtte for å opprette et tilsvarende element. I dette tilfellet har vi markør og banen, henholdsvis.

På den montert krok, vi skaper et element (Markør/Polylinje) og legge den til vår kartet ved å sende kart eiendom til objektet constructor.

Det er fortsatt ett skritt til å gå…

6. Legge til elementer på kartet

La oss bruke vår fabrikk komponenter for å legge til elementer på kartet vårt. Vi må gi fabrikken komponent og passere google og kart objekter slik at data flyter til de riktige stedene.

Vi må også oppgi data som er nødvendig av elementet selv. I vårt tilfelle, som er merket objekt med posisjonen til markøren og banen objekt med Polylinje koordinater.

Her går vi, og integrere data peker direkte inn i malen:

// TravelMap.vue
<mal>
<GoogleMapLoader
:mapConfig=”mapConfig”
apiKey=”yourApiKey”
>
<slot mal-scope=”{ google, kart }”>
<GoogleMapMarker
v-=”markør i markører”
:key=”markør.id”
:markør=”markør”
:google=”google”
:map=”kart”
/>
<GoogleMapLine
v-=”line i linjer”
:key=” – linjen.id”
:bane.synkronisering=” – linjen.banen”
:google=”google”
:map=”kart”
/>
</template>
</GoogleMapLoader>
</template>

Vi trenger å importere den nødvendige fabrikken komponenter i skriptet og angi data som sendes til markører og linjer:

import { mapSettings } fra “@/konstanter/mapSettings”;

eksport standard {
komponenter: {
GoogleMapLoader,
GoogleMapMarker,
GoogleMapLine
},
data() {
tilbake {
markører: [
{ id: “en”, posisjon: { lat: 3, lng: 101 } },
{ id: “b”, posisjon: { lat: 5, lng: 99 } },
{ id: “c”, posisjon: { lat: 6, lng: 97 } }
],
linjer: [
{ id: “1”, bane: [{ lat: 3, lng: 101 }, { lat: 5, lng: 99 }] },
{ id: “2”, bane: [{ lat: 5, lng: 99 }, { lat: 6, lng: 97 }] }
]
};
},
beregnet: {
mapConfig() {
tilbake {
…mapSettings,
center: dette.mapCenter
};
},
mapCenter() {
gå tilbake til denne.markører[1].posisjon;
}
}
};

Og vi er ferdig!

Med alle de biter fullført, kan vi nå re-bruk GoogleMapLoader komponent som en base for alle våre kart ved å sende ulike maler for hver og en av dem. Tenk deg at du trenger for å lage et kart med ulike Markører eller bare Markører uten Polylinjer. Ved hjelp av et mønster av omfattet slots, det blir veldig lett siden alt vi trenger for å passere nå er et annet innhold til GoogleMapLoader komponent.

Dette mønsteret er ikke strengt koblet til Google Maps, den kan brukes med alle bibliotek til å angi grunnleggende komponent og utsette bibliotekets API-et som kan brukes i den komponenten som kalte den grunnleggende komponent.

Det kan være fristende å lage en mer kompleks eller robust løsning, men dette får oss til abstraksjon vi trenger, og det blir en selvstendig del av vår codebase. Hvis vi kommer til det punktet, da kan det være verdt å vurdere utvinning til en add-on.