Svelte中如何将非null的SVG节点传递给子组件?
问题分析与解决方案
问题根源
onMount是组件挂载到DOM后才执行的钩子,初始渲染时svgSelector仍为null,此时{#each}已经完成首次渲染,传递给Hotspot组件的自然是null。- 即便
onMount中给svgSelector完成赋值,若$hotspots没有变化,Svelte不会自动重新执行{#each}来更新子组件的props。
具体解决方案
方案1:延迟渲染子组件,等待svgSelector初始化完成
在{#each}外层添加条件判断,确保svgSelector不为null时才渲染子组件:
<main> {#if svgSelector} {#each $hotspots as hotspot} <Hotspot hotspot={hotspot} svgSelector={svgSelector} /> {/each} {/if} </main>
初始阶段子组件不会渲染,当onMount中svgSelector赋值完成后,Svelte会检测到变量变化,触发重新渲染,此时传递给子组件的就是正确的SVG节点。
方案2:让子组件响应svgSelector的更新
如果需要子组件在svgSelector变化时自动处理,可在Hotspot组件内监听props变化:
<script> export let hotspot; export let svgSelector; // 监听svgSelector的变化,当它不为null时执行业务逻辑 $: if (svgSelector) { // 这里编写基于svgSelector的操作,比如添加热点元素等 } </script>
这样即便初始传入null,后续svgSelector赋值后,子组件也会自动触发对应逻辑,拿到有效的SVG节点。
额外优化:用Svelte绑定代替原生DOM查询(推荐)
Svelte更推荐通过bind:this绑定DOM元素,替代getElementById,代码更符合框架风格:
<script> let svgSelector = null; let mapElement; let mapContainerElement; const renderMap = () => { svgSelector = SVG().addTo(mapElement); svgSelector .size(mapContainerElement.offsetWidth, mapContainerElement.offsetHeight) .viewbox( 0, 0, $activeLayer.background.width, $activeLayer.background.height ); svgSelector.image($activeLayer.background.url); return svgSelector; }; onMount(() => { renderMap(); }); </script> <main> <div bind:this={mapContainerElement}> <div bind:this={mapElement}></div> </div> {#if svgSelector} {#each $hotspots as hotspot} <Hotspot hotspot={hotspot} svgSelector={svgSelector} /> {/each} {/if} </main>
内容的提问来源于stack exchange,提问作者nicolascanala
相关产品推荐
相关产品推荐

