组件内部具有非常奇怪行为的对象
Object with very strange behavior inside component
我有一个行为异常的对象。不知道怎么回事
我的代码:
<script>
import { page } from '$app/stores'
const { listingId } = $page.params
import { db } from '../../../../firebase.config'
import { goto } from '$app/navigation'
import { getDoc, doc } from 'firebase/firestore'
import { getAuth } from 'firebase/auth'
import { scale } from 'svelte/transition'
import LeafletMap from '$lib/LeafletMap.svelte'
let listing = {}
const auth = getAuth()
const fetchListing = async () => {
const docRef = doc(db, 'listings', listingId)
const docSnap = await getDoc(docRef)
if (docSnap.exists) {
listing = docSnap.data()
}
console.log('listing', listing)
}
fetchListing()
// call listing
listing
</script>
<main in:scale>
<div class="listingDetails">
<p class="listingName">
{listing.name} - ${listing.offer ? listing.discountedPrice : listing.regularPrice}
</p>
<p class="listingLocation">
{listing.location}
</p>
<p class="listingType">
Para {listing.type === 'rent' ? 'Alugar' : 'Vender'}
</p>
{#if listing.offer}
<p class="discoutPrice">
${listing.regularPrice - listing.discountedPrice}
de desconto
</p>
{/if}
<ul class="listingDetailsList">
<li>
{#if listing.bedrooms > 1}
{listing.bedrooms} quartos
{/if}
{#if listing.bedrooms === 1}
{listing.bedrooms} quarto
{/if}
</li>
<li>
{#if listing.bathrooms > 1}
{listing.bathrooms} banheiros
{/if}
{#if listing.bathrooms === 1}
{listing.bathrooms} banheiro
{/if}
</li>
<li>
{#if listing.parking == true}
estacionamento
{:else}
sem estacionamento
{/if}
</li>
<li>
{#if listing.furnished == true}
mobiliado
{:else}
não mobiliado
{/if}
</li>
</ul>
<p class="listingLocationTitle">Localização</p>
<LeafletMap lat={'26.2137376'} lng={'-80.2094237'} zoom={15} />
{#if auth.currentUser?.uid == listing.user}
<a href={`/contact/${listing.user}?listingName=${listing.name}`} class="primaryButton">
Entre em contato com o proprietário
</a>
{/if}
</div>
</main>
我的console.log('listing', listing)
里面的函数fetchListing
调用列表:
但是如果我尝试做同样的事情,在函数之外我会得到这个:
这很有趣,因为可以正常工作,但我需要在组件 <LeafletMap/>
中访问 listing.geolocation.lat
和 listing.geolocation.lng
。如果我把这个 {listing.geolocation.lat.toString()}
放在组件外面,我就会得到这个数字。但是如果我这样做:
<LeafletMap lat={listing.geolocation.lat.toString()} lng={'-80.2094237'} zoom={15} />
我明白了error: TypeError: Cannot read properties of undefined (reading 'lat')
我的<LeafletMap/>
组件:
<script>
import { onMount } from 'svelte'
import { browser } from '$app/env'
export let lat
export let lng
onMount(async () => {
if (browser) {
const leaflet = await import('leaflet')
const map = leaflet.map('map').setView([lat, lng], 13)
leaflet
.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution:
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
})
.addTo(map)
leaflet.marker([lat, lng]).addTo(map)
}
})
</script>
<main>
<div id="map" />
</main>
<style>
@import 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.css';
main #map {
height: 800px;
}
</style>
如果我这样做:<LeafletMap lat={'42.233283'} lng={'-80.2094237'} zoom={15} />
我得到了完美的位置,所以,我的组件正在工作。
fetchListing
是一个异步函数,因此在呈现 LeafletMap
时可能不会设置 listing
。
我的建议是 add/update 设置纬度和经度后标记,如下例所示。这还允许您在运行时更新标记,并且可以轻松扩展多个标记。
<script>
export let lat;
export let lng;
let map;
let mounted = false;
$: if (mounted && lat && lng) updateMarkers(lat, lng);
async function updateMarkers(latitude, longitude) {
const leaflet = await import('leaflet');
leaflet.marker([latitude, longitude]).addTo(map);
map.setView([latitude, longitude], 13);
}
async function createMap(container) {
const leaflet = await import('leaflet');
map = leaflet.map(container);
leaflet
.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
})
.addTo(map);
return map;
}
function mapAction(container) {
createMap(container).then(function(map){
mounted = true;
return {
destroy: () => {
map.remove();
}
};
});
}
</script>
<div style={$$props.style} use:mapAction />
<style>
@import 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.css';
div {
height: 800px;
}
</style>
我有一个行为异常的对象。不知道怎么回事
我的代码:
<script>
import { page } from '$app/stores'
const { listingId } = $page.params
import { db } from '../../../../firebase.config'
import { goto } from '$app/navigation'
import { getDoc, doc } from 'firebase/firestore'
import { getAuth } from 'firebase/auth'
import { scale } from 'svelte/transition'
import LeafletMap from '$lib/LeafletMap.svelte'
let listing = {}
const auth = getAuth()
const fetchListing = async () => {
const docRef = doc(db, 'listings', listingId)
const docSnap = await getDoc(docRef)
if (docSnap.exists) {
listing = docSnap.data()
}
console.log('listing', listing)
}
fetchListing()
// call listing
listing
</script>
<main in:scale>
<div class="listingDetails">
<p class="listingName">
{listing.name} - ${listing.offer ? listing.discountedPrice : listing.regularPrice}
</p>
<p class="listingLocation">
{listing.location}
</p>
<p class="listingType">
Para {listing.type === 'rent' ? 'Alugar' : 'Vender'}
</p>
{#if listing.offer}
<p class="discoutPrice">
${listing.regularPrice - listing.discountedPrice}
de desconto
</p>
{/if}
<ul class="listingDetailsList">
<li>
{#if listing.bedrooms > 1}
{listing.bedrooms} quartos
{/if}
{#if listing.bedrooms === 1}
{listing.bedrooms} quarto
{/if}
</li>
<li>
{#if listing.bathrooms > 1}
{listing.bathrooms} banheiros
{/if}
{#if listing.bathrooms === 1}
{listing.bathrooms} banheiro
{/if}
</li>
<li>
{#if listing.parking == true}
estacionamento
{:else}
sem estacionamento
{/if}
</li>
<li>
{#if listing.furnished == true}
mobiliado
{:else}
não mobiliado
{/if}
</li>
</ul>
<p class="listingLocationTitle">Localização</p>
<LeafletMap lat={'26.2137376'} lng={'-80.2094237'} zoom={15} />
{#if auth.currentUser?.uid == listing.user}
<a href={`/contact/${listing.user}?listingName=${listing.name}`} class="primaryButton">
Entre em contato com o proprietário
</a>
{/if}
</div>
</main>
我的console.log('listing', listing)
里面的函数fetchListing
调用列表:
但是如果我尝试做同样的事情,在函数之外我会得到这个:
这很有趣,因为可以正常工作,但我需要在组件 <LeafletMap/>
中访问 listing.geolocation.lat
和 listing.geolocation.lng
。如果我把这个 {listing.geolocation.lat.toString()}
放在组件外面,我就会得到这个数字。但是如果我这样做:
<LeafletMap lat={listing.geolocation.lat.toString()} lng={'-80.2094237'} zoom={15} />
我明白了error: TypeError: Cannot read properties of undefined (reading 'lat')
我的<LeafletMap/>
组件:
<script>
import { onMount } from 'svelte'
import { browser } from '$app/env'
export let lat
export let lng
onMount(async () => {
if (browser) {
const leaflet = await import('leaflet')
const map = leaflet.map('map').setView([lat, lng], 13)
leaflet
.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution:
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
})
.addTo(map)
leaflet.marker([lat, lng]).addTo(map)
}
})
</script>
<main>
<div id="map" />
</main>
<style>
@import 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.css';
main #map {
height: 800px;
}
</style>
如果我这样做:<LeafletMap lat={'42.233283'} lng={'-80.2094237'} zoom={15} />
我得到了完美的位置,所以,我的组件正在工作。
fetchListing
是一个异步函数,因此在呈现 LeafletMap
时可能不会设置 listing
。
我的建议是 add/update 设置纬度和经度后标记,如下例所示。这还允许您在运行时更新标记,并且可以轻松扩展多个标记。
<script>
export let lat;
export let lng;
let map;
let mounted = false;
$: if (mounted && lat && lng) updateMarkers(lat, lng);
async function updateMarkers(latitude, longitude) {
const leaflet = await import('leaflet');
leaflet.marker([latitude, longitude]).addTo(map);
map.setView([latitude, longitude], 13);
}
async function createMap(container) {
const leaflet = await import('leaflet');
map = leaflet.map(container);
leaflet
.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
})
.addTo(map);
return map;
}
function mapAction(container) {
createMap(container).then(function(map){
mounted = true;
return {
destroy: () => {
map.remove();
}
};
});
}
</script>
<div style={$$props.style} use:mapAction />
<style>
@import 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.css';
div {
height: 800px;
}
</style>