【问题标题】:Sapper/Svelte - need @html included content to invoke componentSapper/Svelte - 需要 @html 包含的内容来调用组件
【发布时间】:2021-04-05 14:17:47
【问题描述】:

我正在使用sapper 构建一个站点,该站点对单个博客条目使用[slug].svelte 约定。博客内容来自(模拟)数据库,并包含 html。

html 包含在底部,如下所示:

...
<div class="content">
  {@html post.html}
</div>
...

一切都很好,它使 html 变得很漂亮。

但是,请考虑以下事项:

[slug].svelte 文件中:

import AComponent from '../../components/AComponent.svelte'

并且,在包含的 html 里面渲染了{@html post.html}

<p>yada yada yada</p>
<AComponent prop="data" />
<p>More yada yada yada...</p>

AComponent 不会被实例化或调用。

有没有办法做到这一点?还是我在尝试做一些不可能的事情?

(我知道组件没问题 - 它已在另一个包含完整 html 的文件中进行了测试。)

感谢

【问题讨论】:

    标签: javascript svelte sapper


    【解决方案1】:

    我不相信单独使用 @html 指令是不可能的。

    来自the docs

    表达式应该是有效的独立 HTML — {@html "&lt;div&gt;"}content{@html "&lt;/div&gt;"} 无效,因为它不是有效的 HTML。

    由于&lt;AComponent prop="data" /&gt; 是一个 Svelte 组件而不是独立的 HTML,因此在使用 @html 时它不会实例化自己。

    但是,您可以使用&lt;svelte:component&gt; 组合一个解决方案,从字符串内容动态呈现组件。

    这是Svelte REPL 中的快速概念证明。有很多边缘情况未被发现,但它表明这是可能的。我也粘贴了下面的代码。

    <script>
        import ComponentA from './ComponentA.svelte';
        import ComponentB from './ComponentB.svelte';
        
        let raw = `<p>yada yada yada</p>
    <ComponentA name="testing" />
    <p>More yada yada yada...</p>`;
        
        $: rawLines = raw.split('\n');
        
        function getComponent(line) {
            const componentName = line.split(' ')[0].substring(1);
            switch (componentName) {
                case 'ComponentA':
                    return ComponentA;
                case 'ComponentB':
                    return ComponentB;
            }
            return null;
        }
        
        function getComponentProps(line) {
            const props = line.split(' ').slice(1, -1);
            const kvPairs = props.map(p => p.replaceAll('"', '').split('='));
            return Object.fromEntries(kvPairs);
        }
    </script>
    
    <textarea bind:value={raw} />
    {#each rawLines as line}
        {#if line[1] === line[1].toUpperCase()}
            <svelte:component this={getComponent(line)} {...getComponentProps(line)}></svelte:component>
        {:else}
            {@html line}
        {/if}
    {/each}
    

    【讨论】:

    • 有趣的想法。我最终编写了一个预处理器,将代码片段注入模板文件,并将命名文件写入“src/routes/blog/”文件夹。 svelte 编译器像往常一样从那里获取它。也许不是最优雅的解决方案,但它确实有效。它在编辑时失去了实时更新能力,所以我在进行编辑时必须重新编译。另外,我想我可以从中调用其他预处理器,例如降价处理器。
    猜你喜欢
    • 2020-01-07
    • 2015-11-30
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    相关资源
    最近更新 更多