- Pelajari
-
Ekosistem
Pertolongan
Alat
Pustaka Inti
Berita
Daftar Sumber Daya
- Tim
- Dukung Vue
- Terjemahan
Buku Petunjukbeta
- Pengantar
- Menambah Properti Instance
- Validasi Form
- Editable SVG Icon Systems
- Membuat Blog Bertenaga CMS
- Unit Tes Komponen Vue
- Membuat Scroll Directives Khusus
- Debug menggunakan VS Code
- Menggunakan Axios untuk Mengkonsumsi API
- Penyimpanan Data di Sisi Klien
- Dockerize Aplikasi Vue.js App
- Penggunaan praktis dari slot scoped dengan GoogleMaps
Penggunaan praktis dari slot scoped dengan GoogleMaps
Contoh Dasar
Ada beberapa situasi ketika Anda menginginkan templat dalam slot untuk bisa mengakses data dari child component yang bertanggung jawab untuk menrender slot konten. Sebagian ini berguna ketika Anda membutuhkan kebebasan dalam membuat templat khusus yang menggunakan beberapa properti data child component. Kasus penggunaan umum untuk slot scoped.
Bayangkan sebuah komponen yang terkonfigurasi dan menyiapkan API eksternal untuk digunakan di komponen lain, tapi tidak tergabung erat dengan templat spesifik manapun. Seperti sebuah komponen dapat diguna-ulang dalam banyak tempat merender templat berbeda tapi menggunakan obyek dasar yang sama dengan API spesifik.
Kita akan membuat sebuah komponen (GoogleMapLoader.vue
):
- Inisialisasi Google Maps API
- Buat obyek
google
danmap
- Buka obyek tersebut untuk parent component yang menggunakan
GoogleMapLoader
Di bawah adalah contoh bagaimana ini bisa dicapai. Kita akan menganalisis kode sepotong-sepotong dan melihat apa yang sebenarnya terjadi dalam seksi berikutnya.
Pertama-tama buat GoogleMapLoader.vue
templat kita
<template>
<div>
<div class="google-map" ref="googleMap"></div>
<template v-if="Boolean(this.google) && Boolean(this.map)">
<slot
:google="google"
:map="map"
/>
</template>
</div>
</template>
Sekarang, kebutuhan skrip kita untuk mengoper beberapa props ke komponen yang mengizinkan kita untuk menetapkan Google Maps API dan Map object:
import GoogleMapsApiLoader from 'google-maps-api-loader'
export default {
props: {
mapConfig: Object,
apiKey: String,
},
data() {
return {
google: null,
map: null
}
},
async mounted() {
const googleMapApi = await GoogleMapsApiLoader({
apiKey: this.apiKey
})
this.google = googleMapApi
this.initializeMap()
},
methods: {
initializeMap() {
const mapContainer = this.$refs.googleMap
this.map = new this.google.maps.Map(
mapContainer, this.mapConfig
)
}
}
}
Ini hanyalah bagian dari contoh kerja, Anda dapat mencari seluruh contoh di Codesandbox di bawah.
Contoh Nyata: Membuat sebuah komponen Pemuat Google Map
1. Buat sebuah komponen yang menginisialisasi map kita
GoogleMapLoader.vue
Dalam templat, kita membuat sebuah kontainer untuk peta yang akan digunakan untuk memasang Map obyek yang diekstraksi dari API Google Maps.
<template>
<div>
<div class="google-map" ref="googleMap"></div>
</div>
</template>
Berikutnya, skrip kita butuh untuk menerima props dari parent component yang akan mengizinkan kita untuk menetapkan Google Map. Props tersebut terdiri dari:
import GoogleMapsApiLoader from 'google-maps-api-loader'
export default {
props: {
mapConfig: Object,
apiKey: String,
},
Lalu, kita menetapkan nilai inisial dari google dan map menjadi null:
data() {
return {
google: null,
map: null
}
},
Dalam kait mounted
kita instantiate sebuah googleMapApi
dan obyek Map
dari GoogleMapsApi
dan kita menetapkan nilai dari google
dan map
untuk membuat instance:
async mounted() {
const googleMapApi = await GoogleMapsApiLoader({
apiKey: this.apiKey
})
this.google = googleMapApi
this.initializeMap()
},
methods: {
initializeMap() {
const mapContainer = this.$refs.googleMap
this.map = new this.google.maps.Map(mapContainer, this.mapConfig)
}
}
}
Sejauh ini bagus. Dengan semua yang telah selesai, kita bisa melanjutkan menambahkan ke obyek lain ke dalam peta (Marker, Polyline, dll.) dan gunakan sebagai komponen peta biasa.
Tapi, kita ingin menggunakan komponen GoogleMapLoaded
kita saja sebagai pemuat yang menyiapkan peta — kita tidak ingin merender apapun didalamnya.
Untuk mencapai itu, kita perlu mengizinkan parent component yang akan menggunakan GoogleMapLoader
kita untuk mengakses this.google
dan this.map
yang ditetapkan dalam komponen GoogleMapLoader
. Itulah dimana slot scoped terlihat bersinar. Slot scoped mengizinkan kita untuk membuka pengaturan properti di sebuah child component ke parent component. Ini terdengar seperti permulaan, tapi bertahanlah beberapa menit untuk
kita urai lebih dalam.
2. Membuat komponen yang menggunakan penginisialisasi komponen kita.
TravelMap.vue
Dalam templat, kita merender komponen GoogleMapLoader
dan mengoper props yang dibutuhkan untuk menginisialisasi peta.
<template>
<GoogleMapLoader
:mapConfig="mapConfig"
apiKey="yourApiKey"
/>
</template>
Tag skrip kita akan terlihat seperti ini:
<script>
import GoogleMapLoader from './GoogleMapLoader'
import { mapSettings } from '@/constants/mapSettings'
export default {
components: {
GoogleMapLoader
},
computed: {
mapConfig () {
return {
...mapSettings,
center: { lat: 0, lng: 0 }
}
},
},
}
</script>
Masih tanpa slot scoped, jadi mari tambahkan satu.
3. Membuka properti google
dan map
ke parent component dengan menambahkan slot scoped.
Akhirnya, kita akan menambahkan slot scoped yang akan melakukan pekerjaannya dan mengizinkan kita untuk mengakses props child component di parent component. Kita melakukannya dengan menambahkan tag <slot>
dalam child component dan mengoper props yang kita inginkan untuk dibuka (menggunakan directive v-bind
atau tulisan cepat :propName
). Ini tidak berbeda dari mengoper props turuh ke child component, tapi dengan melakukan ini dalam tag <slot>
akan membalikan arah
dari aliran data.
GoogleMapLoader.vue
<template>
<div>
<div class="google-map" ref="googleMap"></div>
<template v-if="Boolean(this.google) && Boolean(this.map)">
<slot
:google="google"
:map="map"
/>
</template>
</div>
</template>
Sekarang, ketika kita memiliki slot dalam child component, kita perlu menerima dan mengkonsumsi props yang dibuka di parent component.
4. Menerima props yang dibuka di parent component menggunakan atribut slot-scope
.
Untuk menerima props di parent component, kita mendeklarasikan sebuauh elemen templat dan menggunakan atribut slot-scope
. Atribut ini memiliki akses ke obyek yang membawa semua props yang dibuka dari child component. Kita bisa mengambil seluruh obyek atau kita bisa menghancurkan obyek tersebut dan hanya apa yang kita butuhkan
Mari hancurkan benda ini untuk mendapatkan apa yang kita butuhkan.
TravelMap.vue
<GoogleMapLoader
:mapConfig="mapConfig"
apiKey="yourApiKey"
>
<template slot-scope="{ google, map }">
{{ map }}
{{ google }}
</template>
</GoogleMapLoader>
Meskipun props google
dan map
tidak ada di scope TravelMap
, komponen masih memiliki akses ke props (props dari google
dan map
) dan kita dapat menggunakannya dalam templat.
Anda mungkin takjub mengapa kita mau melakukan hal seperti itu dan apa gunanya semua itu?
Slot scoped mengizinkan kita untuk mengoper templat ke slot sebagai ganti dari elemen yang telah dirender. Itu disebut slot scoped
karena itu akan memiliki akses ke data child component tertentu meskipun templat telah dirender dalam scope parent component. Ini memberikan kita kebebasan untuk mengisi templat dengan konten khusu dari parent component.
5. Membuat komponen pabrik dari Marker dan Polyline
Sekarang ketika kita memiliki peta kita siap kita akan membuat 2 komponen pabrik yang akan digunakan untuk menambah elemen ke TravelMap
.
GoogleMapMarker.vue
import { POINT_MARKER_ICON_CONFIG } from '@/constants/mapSettings'
export default {
props: {
google: {
type: Object,
required: true
},
map: {
type: Object,
required: true
},
marker: {
type: Object,
required: true
}
},
mounted() {
new this.google.maps.Marker({
position: this.marker.position,
marker: this.marker,
map: this.map,
icon: POINT_MARKER_ICON_CONFIG
})
}
}
GoogleMapLine.vue
import { LINE_PATH_CONFIG } from '@/constants/mapSettings'
export default {
props: {
google: {
type: Object,
required: true
},
map: {
type: Object,
required: true
},
path: {
type: Array,
required: true
}
},
mounted() {
new this.google.maps.Polyline({
path: this.path,
map: this.map,
...LINE_PATH_CONFIG
})
}
}
Keduanya menerima google
yang kita gunakan untuk mengekstraksi obyek yang dibutuhkan (Marker atau Polyline) sebaik map
yang diberikan sebagai referensi ke peta di mana kita ingin menempatkan elemen kita.
Masing-masing komponen juga berekspektasi prop tambahan untuk membuat elemen yang sesuai. Dalam kasus ini, kita memiliki marker
dan path
, masing-masing.
Dalam kait yang terpasang, kita membuat sebuah elemen (Marker/Polyline) dan melampirkannya ke peta kita dengan mengoper properti map
untuk konstruktor obyek.
Masih ada satu langkah lagi…
6. Menambah elemen ke peta
Mari gunakan komponen pabrik kita untuk menambah elemen ke peta kita. Kita harus merender komponen pabrik dan mengoper obyek google
dan peta
jadi aliran data menuju ke tempat yang tepat.
Kita juga perlu menyediakan data yang dibutuhkan oleh elemen itu sendiri. Dalam kasus kita adalah obyek marker
dengan posisi dari marker dan obyek path
dengan koordinat Polyline/
Kita mulai, mengintegrasi poin data langsung ke templat:
<GoogleMapLoader
:mapConfig="mapConfig"
apiKey="yourApiKey"
>
<template slot-scope="{ google, map }">
<GoogleMapMarker
v-for="marker in markers"
:key="marker.id"
:marker="marker"
:google="google"
:map="map"
/>
<GoogleMapLine
v-for="line in lines"
:key="line.id"
:path.sync="line.path"
:google="google"
:map="map"
/>
</template>
</GoogleMapLoader>
Kita perlu mengimpor komponen pabrik yang dibutuhkan di skrip kita dan menetapkan data yang akan dioper ke marker dan garis:
import { mapSettings } from '@/constants/mapSettings'
export default {
components: {
GoogleMapLoader,
GoogleMapMarker,
GoogleMapLine
},
data () {
return {
markers: [
{ id: 'a', position: { lat: 3, lng: 101 } },
{ id: 'b', position: { lat: 5, lng: 99 } },
{ id: 'c', position: { lat: 6, lng: 97 } },
],
lines: [
{ id: '1', path: [{ lat: 3, lng: 101 }, { lat: 5, lng: 99 }] },
{ id: '2', path: [{ lat: 5, lng: 99 }, { lat: 6, lng: 97 }] }
],
}
},
computed: {
mapConfig () {
return {
...mapSettings,
center: this.mapCenter
}
},
mapCenter () {
return this.markers[1].position
}
},
}
Kapan Untuk Menghindari Pola Ini
Ini mungkin menggoda untuk membuat solusi yang sangat kompleks berdasarkan contoh, tapi dalam beberapa poin kita dapat sampai pada situasi dimana abstraksi ini menjadi bagian yang mandiri dari kode yang berada dalam basis kode.
Kesimpulan
Jadi itu saja. Dengan semua bit-bit itu dan bagian-bagian yang telah dibuat sekarang kita dapat menguna-ulang komponen GoogleMapLoader
sebagai dasar untuk semua peta kita dengan mengoper tempat berbeda ke masing-masing templat tersebut. Bayangkan Anda perlu membuat peta lain dengan Marker yang berbeda atau hanya Marker tanpa Polyline. Dengan menggunakan pola di atas itu menjadi sangat mudah seperti kita hanya perlu mengoper konten yang berbeda ke komponen GoogleMapLoader
.
Pola ini tidak ketat terkoneksi ke Google Maps; ini dapat digunakan dengan pustaka apapun untuk menetapkan dasar komponen dan membuka pustaka API yang mungkin digunakan dalam komponen yang dipanggil komponen dasar.