W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
上下文 API 為組件提供了一種機(jī)制,可以在不傳遞數(shù)據(jù)和函數(shù)作為 props 或分派大量事件的情況下相互“交談”。這是一項(xiàng)高級(jí)功能,但很有用。
以使用 Mapbox GL 地圖的示例應(yīng)用程序?yàn)槔?。我們想使?nbsp;<MapMarker> 組件顯示標(biāo)記,但我們不想傳遞對(duì)底層 Mapbox 實(shí)例的引用作為每個(gè)組件的 prop。
上下文 API 有兩部分 — ?setContext
? 和 ?getContext
?。如果組件調(diào)用 ?setContext(key, context)
?,則任何子組件都可以使用 ?const context = getContext(key)
? 檢索上下文。
讓我們先設(shè)置上下文。在 ?Map.svelte
? 中,從 ?svelte
? 導(dǎo)入 ?setContext
?,從 ?mapbox.js
? 導(dǎo)入 ?key
? 并調(diào)用 ?setContext
?:
import { onMount, setContext } from 'svelte';
import { mapbox, key } from './mapbox.js';
setContext(key, {
getMap: () => map
});
上下文對(duì)象可以是您喜歡的任何內(nèi)容。與生命周期函數(shù)一樣,?setContext
? 和 ?getContext
? 必須在組件初始化期間調(diào)用;由于 ?map
? 在組件掛載之前不會(huì)創(chuàng)建,因此我們的 context 對(duì)象包含一個(gè) ?getMap
? 函數(shù)而不是 ?map
? 本身。
在等式的另一邊,在 ?MapMarker.svelte
? 中,我們現(xiàn)在可以獲得對(duì) Mapbox 實(shí)例的引用:
import { getContext } from 'svelte';
import { mapbox, key } from './mapbox.js';
const { getMap } = getContext(key);
const map = getMap();
標(biāo)記現(xiàn)在可以將自己添加到地圖中。
更完善的 ?
<MapMarker>
? 版本也可以處理移除和屬性更改,但我們?cè)谶@里只演示上下文。
在 ?mapbox.js
? 中你會(huì)看到這一行:
const key = {};
我們可以使用任何東西作為鍵——例如我們可以做 ?setContext('mapbox', ...)
? 。使用字符串的缺點(diǎn)是不同的組件庫(kù)可能會(huì)意外地使用同一個(gè)字符串;使用對(duì)象字面量意味著鍵在任何情況下都保證不會(huì)發(fā)生沖突(因?yàn)橐粋€(gè)對(duì)象只對(duì)自身具有引用相等性,即 ?{} !== {}
? 而?“x”===“x”
?),即使你有跨多個(gè)組件層運(yùn)行的多個(gè)不同上下文。
Contexts 和 stores 看起來(lái)很相似。它們的不同之處在于,stores 可用于應(yīng)用程序的任何部分,而 context 僅可用于組件及其后代。如果你想使用一個(gè)組件的多個(gè)實(shí)例,而一個(gè)組件的狀態(tài)不會(huì)干擾其他組件的狀態(tài),這會(huì)很有幫助。
事實(shí)上,您可以將兩者結(jié)合使用。由于 context 不是反應(yīng)性的,因此隨時(shí)間變化的值應(yīng)該表示為存儲(chǔ):
const { these, are, stores } = getContext(...);
示例代碼
<script>
import Map from './Map.svelte';
import MapMarker from './MapMarker.svelte';
</script>
<Map lat={35} lon={-84} zoom={3.5}>
<MapMarker lat={37.8225} lon={-122.0024} label="Svelte Body Shaping"/>
<MapMarker lat={33.8981} lon={-118.4169} label="Svelte Barbershop & Essentials"/>
<MapMarker lat={29.7230} lon={-95.4189} label="Svelte Waxing Studio"/>
<MapMarker lat={28.3378} lon={-81.3966} label="Svelte 30 Nutritional Consultants"/>
<MapMarker lat={40.6483} lon={-74.0237} label="Svelte Brands LLC"/>
<MapMarker lat={40.6986} lon={-74.4100} label="Svelte Medical Systems"/>
</Map>
<script>
import { onMount, setContext } from 'svelte';
import { mapbox, key } from './mapbox.js';
setContext(key, {
getMap: () => map
});
export let lat;
export let lon;
export let zoom;
let container;
let map;
onMount(() => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.;
link.onload = () => {
map = new mapbox.Map({
container,
style: 'mapbox://styles/mapbox/streets-v9',
center: [lon, lat],
zoom
});
};
document.head.appendChild(link);
return () => {
map.remove();
link.parentNode.removeChild(link);
};
});
</script>
<style>
div {
width: 100%;
height: 100%;
}
</style>
<div bind:this={container}>
{#if map}
<slot></slot>
{/if}
</div>
<script>
import { getContext } from 'svelte';
import { mapbox, key } from './mapbox.js';
const { getMap } = getContext(key);
const map = getMap();
export let lat;
export let lon;
export let label;
const popup = new mapbox.Popup({ offset: 25 })
.setText(label);
const marker = new mapbox.Marker()
.setLngLat([lon, lat])
.setPopup(popup)
.addTo(map);
</script>
import mapbox from 'mapbox-gl';
// https://docs.mapbox.com/help/glossary/access-token/
mapbox.accessToken = MAPBOX_ACCESS_TOKEN;
const key = {};
export { mapbox, key };
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: