首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有小叶的苗条

有小叶的苗条
EN

Stack Overflow用户
提问于 2020-06-14 15:02:31
回答 1查看 1.7K关注 0票数 4

我想找到一条通往斯维特的路,结合传单。我被困的地方是如何正确地将传单组件分割成文件。为了学习,我尝试用svelte构建正式的官方传单快速启动

这就是我的app.svelte的样子:

代码语言:javascript
复制
<script>
  import L from 'leaflet';
  import { onMount } from "svelte";
  import { Circle } from "./components/Circle.svelte";

  let map;

  onMount(async () => {
    map = L.map("map");

    L.tileLayer("https://a.tile.openstreetmap.org/{z}/{x}/{y}.png ", {
      attribution:
        'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
      maxZoom: 18,
        tileSize: 512,
        zoomOffset: -1
    }).addTo(map);

    map.setView([51.505, -0.09], 13);
    Circle.addTo(map);

  });
</script>

<style>
    html,body {
        padding: 0;
        margin: 0;
    }
    html, body, #map {
        height: 100%;
        width: 100vw;
    }
</style>

<svelte:head>
    <link
    rel="stylesheet"
    href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
    integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
    crossorigin="" />
</svelte:head>

<div id="map" />

我的圆圈部分:

代码语言:javascript
复制
<script context="module">
    import L from 'leaflet';
    export let map_obj;

    export let Circle = L.circle([51.508, -0.11], {
        color: "red",
        fillColor: '#f03',
        fillOpacity: 0.5,
        radius: 500
    });
</script>

虽然这是可行的,但我认为考虑每个组件并使用Circle.addTo(map);将其添加到映射中并不是有效的。如何将map对象传递给圆形组件,或者是否有更好的模式来构建包含多个组件的映射?

注意:我确实知道细长/小叶,但我喜欢从零开始学习。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-14 16:51:54

这个看似简单的任务是复杂的,因为像Svelte这样的框架的生命周期并不是非常简单,而且传单中真正简单的让我做DOM的架构也是如此。

要做到这一点,有几种方法。我将描述一个,基于为传单映射的Svelte组件内的传单层嵌套Svelte组件,并使用setContextgetContext来处理传单L.Map实例。(我从https://github.com/beyonk-adventures/svelte-mapbox借用这一技术)

因此,用于L.Marker的Svelte组件如下所示:

代码语言:javascript
复制
<script>
    import L from 'leaflet';
    import { getContext } from "svelte";

    export let lat = 0;
    export let lng = 0;

    let map = getContext('leafletMapInstance');

    L.marker([lat, lng]).addTo(map);
</script>

非常简单--通过L.Map从Svelte上下文中获取getContext实例,实例化L.Marker,添加它。这意味着地图必须有一个Svelte组件来设置上下文,这将需要在其中设置标记的组件,即

代码语言:javascript
复制
<script>
    import LeafletMap from './LeafletMap.svelte'
    import LeafletMarker from './LeafletMarker.svelte'
</script>

<LeafletMap>
    <LeafletMarker lat=40 lng=-3></LeafletMarker>
    <LeafletMarker lat=60 lng=10></LeafletMarker>
</LeafletMap>

...and然后传单映射的Svelte组件将创建L.Map实例,将其设置为上下文,并完成,对吗?还没那么快。这就是事情变得奇怪的地方。

由于Svelte生命周期的工作方式,子组件将在父组件之前得到“呈现”,但是父组件需要一个DOM元素来创建L.Map实例(即映射容器)。因此,这可能会延迟到onRender Svelte生命周期回调,但这将发生在时隙子节点实例化并调用它们的onRender生命周期回调之后。因此,等待Svelte实例化DOM元素以包含映射,然后实例化L.Map,然后将该实例传递给上下文,然后在标记元素中获取上下文,这将是一场噩梦。

因此,一种方法是创建一个独立的DOM元素,在那里实例化一个L.Map,即.

代码语言:javascript
复制
let map = L.map(L.DomUtil.create('div')

在上下文中...set它,即.

代码语言:javascript
复制
import { setContext } from "svelte";
setContext('leafletMapInstance', map);

...this将允许将由时隙组件实例化的传单层添加到独立(因此是不可见的)映射中。一旦所有的生命周期组件都允许L.Map的Svelte组件有一个实际的DOM元素附加到DOM,那么就将映射容器附加到它,即在Svelte组件的HTML部分中.

代码语言:javascript
复制
<div class='map' bind:this={mapContainer}>

...and一旦实际附加到DOM,就将映射容器附加到它并设置它的大小,即.

代码语言:javascript
复制
let mapContainer;
onMount(function() {
    mapContainer.appendChild(map.getContainer());
    map.getContainer().style.width = '100%';
    map.getContainer().style.height = '100%';
    map.invalidateSize();
});

所以这个传单L.Map的整个Svelte组件看起来有点像.

代码语言:javascript
复制
<script>
  import L from "leaflet";
  import { setContext, onMount } from "svelte";

  let mapContainer;
  let map = L.map(L.DomUtil.create("div"), {
    center: [0, 0],
    zoom: 0,
  });
  setContext("leafletMapInstance", map);
  console.log("map", map);

  L.tileLayer("https://a.tile.openstreetmap.org/{z}/{x}/{y}.png ", {
    attribution:
      'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
  }).addTo(map);

  onMount(() => {
    mapContainer.appendChild(map.getContainer());
    map.getContainer().style.width = "100%";
    map.getContainer().style.height = "100%";
    map.invalidateSize();
  });
</script>
<svelte:head>
  <link
    rel="stylesheet"
    href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
    integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
    crossorigin=""
  />
</svelte:head>
<style>
  .map {
    height: 100vh;
    width: 100vw;
  }
</style>
<div class="map" bind:this="{mapContainer}">
  <slot></slot>
</div>

看一个这里的工作示例

顺便提一句,我要说的是,在将传单夹到另一个JS框架中之前,应该三思而后行,并考虑一下这个框架的体系结构(有槽的组件看起来是最干净和最可扩展的,但也许大数据结构和对传单位的一些必要的编程会更简单)。有时,理解同时工作的多个框架的生命周期含义可能会非常令人困惑,并且在出现bug时非常耗时。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62374265

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档