当前位置: 首页 > 知识库问答 >
问题:

带传单的苗条

柳培
2023-03-14

我正在努力找到我的方式,以苗条结合传单。我遇到的问题是如何正确地将传单组件拆分为文件。为了学习,我正在尝试用Svelte构建官方的官方传单quickstart。

这就是我的App.Svelte的样子:

<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" />

和“我的圈子”组件:

<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对象传递给circle组件,或者是否有更好的模式来构建包含多个组件的map?

注意:我知道Svelte/传单,但喜欢从零开始学习。

共有1个答案

颜瀚漠
2023-03-14

由于像Svelte这样的框架的生命周期并不是很简单,而且let-me-do-DOM-stuff架构也很简单,所以这个看似容易的任务变得很复杂。

这有几种方法。我将描述一种方法,其基础是在传单映射的Svelte组件中嵌套传单层的Svelte组件,并使用SetContextGetContext处理周围的传单L.map实例。(我从https://github.com/beyonk-adventures/svelte-mapbox借用了这个技术)

因此,L.marker的一个纤细组件如下所示:

<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>

很简单-通过getcontext从Svelte上下文获取l.map实例,实例化l.marker并添加它。这意味着必须有一个用于设置上下文的映射的Svelte组件,这将需要用于插入的标记的组件,即。

<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>

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

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

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

let map = L.map(L.DomUtil.create('div')

...在上下文中设置,即...

import { setContext } from "svelte";
setContext('leafletMapInstance', map);

...这将允许将由开槽组件实例化的传单层添加到分离的(因此是不可见的)映射中。一旦所有的生命周期内容都允许l.map的Svelte组件有一个实际的DOM元素附加到DOM上,就将map容器附加到它,即在Svelte组件的HTML部分中...

<div class='map' bind:this={mapContainer}>

...并且一旦它实际附加到DOM上,就将地图容器附加到它并设置它的大小,即...

let mapContainer;
onMount(function() {
    mapContainer.appendChild(map.getContainer());
    map.getContainer().style.width = '100%';
    map.getContainer().style.height = '100%';
    map.invalidateSize();
});

因此,这个传单L.map的整个Svelte组件看起来或多或少都像...

<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时非常耗时。

 类似资料:
  • 代码在文章的末尾。剧透:我还发现jit代码胖了224字节,即使它实际上应该更简单(就像字节代码大小显示的那样;请参见下面的最新更新)。 即使在尝试使用一些微基准测试工具(JMH)来消除这种影响之后,性能差异仍然存在。 我在问:为什么生成的本机代码会有这样的差异,它在做什么? 通过给一个方法添加一个参数,它使它更快...!我知道GC/JIT/Warmup/etc的影响。您可以按原样运行代码,也可以使

  • 我正在寻找一个docker映像来构建一个java应用程序,并查看可用的OpenJDK映像的变体。我在这里查看https://github.com/docker-library/openjdk/tree/master/8/jdk,可以看到alpine、slim和Windows。这些之间有什么区别,每个变体都给出了什么?

  • 问题内容: 我希望拿起一个docker映像来构建一个Java应用程序,并查看可用的OpenJDK映像的变体。我在这里https://github.com/docker- library/openjdk/tree/master/8/jdk ,看到阿尔卑斯山,细长的窗户。这些之间有什么区别,每个变体都有什么区别? 问题答案: 每个Docker库文档(下面的引号和链接)为摘要: 实际图像。如果不确定,请

  • 我在Wordpress上有一个旋转木马。我发现我不能在Chrome上点击任何项目链接,但当我使用Safari或Firefox时,它工作得很好。你可以看到我住在这里。我认为这是因为Safari/Firefox中旋转木马的辅助功能无法在项目之间拖动移动,但所有链接都可以工作。

  • 下面是我的代码。我正在用一张传单画一张用Svelte的曲线图。但我得到一个错误“地图未定义”。我该怎么解决这个? 此外,我想添加一个图像作为背景,坐标绘制在给定的图像上。

  • 我只想传递一个lambda(代码块),并在需要时执行它。如何在下面的代码中实现方法(以及方法签名是什么):