Svelte:能否通过Slots与Context API捕获SVG定义?
实现CaptureSVGDef组件捕获子组件SVG定义到正确层级
完全可以通过Svelte的Context API和Slots实现这个需求,核心思路是在根组件SCGDraw中提供一个收集SVG定义的上下文,让子组件里的CaptureSVGDef将内部的SVG定义传递到根组件的<defs>区域,而非在子组件自身位置渲染。
1. 改造SCGDraw.svelte,提供收集SVG定义的上下文
<script lang="ts"> import { setContext } from 'svelte'; import SVGDefs from './SVGDefs.svelte'; import Background from './Background.svelte'; // 存储收集到的SVG定义元素 let svgDefs: Array<HTMLElement> = []; // 提供给子组件的添加方法 const addSVGDef = (def: HTMLElement) => { svgDefs = [...svgDefs, def]; }; // 设置上下文,让子组件可以访问添加方法 setContext('svgDefCollector', addSVGDef); </script> <svg xmlns="http://www.w3.org/2000/svg" width="1020" height="2400"> <slot name="svg-defs"> <SVGDefs /> <!-- 渲染收集到的所有子组件SVG定义 --> {#each svgDefs as def} {@html def.outerHTML} {/each} </slot> <slot name="scene-background"> <Background /> </slot> </svg>
这里通过setContext暴露addSVGDef方法,子组件可调用该方法传递SVG定义,最终在svg-defs插槽统一渲染所有收集到的定义。
2. 实现CaptureSVGDef.svelte组件
<script lang="ts"> import { getContext, onMount } from 'svelte'; // 获取上下文里的收集方法 const addSVGDef = getContext<(def: HTMLElement) => void>('svgDefCollector'); // 引用插槽内容的容器 let defContainer: HTMLElement; onMount(() => { // 把插槽里的SVG定义元素传递给根组件 if (defContainer.children.length > 0 && addSVGDef) { Array.from(defContainer.children).forEach(child => { addSVGDef(child as HTMLElement); }); } }); </script> <!-- 这个容器仅用于捕获插槽内容,不会在页面渲染 --> <div bind:this={defContainer} style="display: none;"> <slot /> </div>
CaptureSVGDef通过getContext获取根组件的收集方法,在组件挂载后将插槽内的SVG定义传递到根组件,自身用隐藏容器捕获内容,不影响页面布局。
3. 修正并使用Background.svelte
<script lang="ts"> import CaptureSVGDef from './CaptureSVGDef.svelte'; </script> <CaptureSVGDef> <linearGradient id="background-gradient"> <stop offset="0%" stop-color="#f0f0f0" /> <stop offset="100%" stop-color="#e0e0e0" /> </linearGradient> </CaptureSVGDef> <rect x={0} y={0} width={1020} height={2400} style={`fill: url(#background-gradient)`} />
修正了示例中的拼写错误(如VaptureSVGDef→CaptureSVGDef),现在Background里的渐变定义会被CaptureSVGDef捕获并传递到SCGDraw的defs区域,rect可正确引用该渐变ID。
内容的提问来源于stack exchange,提问作者Hefeust CORTES
相关产品推荐
相关产品推荐

