【问题标题】:Emit truly "raw" html in Svelte在 Svelte 中发出真正“原始”的 html
【发布时间】:2020-06-08 14:00:17
【问题描述】:

我从无头 CMS 接收原始 html sn-ps,我需要在 Sapper 应用程序中按原样呈现。

这也包括我收到一个开始标签和相应的结束标签作为两段 HTML 的情况,我在这两条 HTML 之间添加了一个 Svelte 组件。

<script>
    import MyComponent from './MyComponent.svelte'

    // example snippets coming from headless CMS
    const prefix = '<p class="test">' 
    const suffix = '</p>'
</script>

<!-- use snippets as-is -->
{@html prefix}
<MyComponent />
{@html suffix}

https://svelte.dev/repl/4c1bf80ae00e476587344b6065e7346e?version=3.19.1

但是,Svelte 期望使用 @html 呈现的每个项目都是自包含元素,并尝试“修复”常见错误。例如,它会在 prefix-sn-p 中添加一个结束标签,将&lt;MyComponent/&gt;-part 移出p

有没有办法在一般情况下规避这种行为?或者更具体地说 - 是否可以用任意原始 HTML 包围渲染的组件?

作为一个侧节点:它作为一个 sapper 应用程序运行,并且页面的服务器端渲染版本确实正确地发出了原始 HTML。当客户端渲染开始时,行为会发生变化。

【问题讨论】:

    标签: javascript svelte sapper


    【解决方案1】:

    您可以使用插槽来通过将组件包装在另一个组件中来获得类似的结果。这是官方文档:https://svelte.dev/tutorial/slots

    【讨论】:

    • 我知道(并使用)插槽,但我不确定他们将如何帮助我。 html sn-ps 是服务器返回的字符串。它们本身并不是可以使用插槽机制的组件。
    • 这个能帮到你吗?:&lt;script&gt; const prefix = '&lt;p class="test"&gt;' ; const suffix = '&lt;/p&gt;'; const getComposed = () =&gt; { return prefix + '&lt;MyComponent/&gt;' + suffix; } &lt;/script&gt; { @html getComposed() }
    • 那行不通。 Svelte 不会将“”解释为要实例化的组件。最终的 HTML 将类似于 &lt;p class="test"&gt;&lt;mycomponent/&gt;&lt;/p&gt;,而完全不涉及 MyComponent。
    【解决方案2】:

    这是一个邪恶的方式......

    免责声明将 Svelte 托管元素移到其脚下可能不是一个好主意,我完全无法理解您接下来可能会遇到什么不良副作用!

    我特别建议不要在 {#each} 块中使用它,尤其是键控块,因为 Svelte 会想要对其元素重新排序,如果它们不在 DOM 中的预期位置,可能会感到不安。

    ...但也许它可以让你在简单的情况下摆脱困境。你是法官。

    我的想法是渲染完整的串联字符串(前缀 + 后缀),并带有一个附加元素,我可以在该片段之外抓取并替换为已由 Svelte 独立渲染的组件。

    这是诀窍:

    {@html prefix + '<span id="vslot"></span>' + suffix}
    

    这是一个实现该技巧的示例组件:

    <script>
        import { afterUpdate } from 'svelte'
    
        export let prefix
        export let suffix
    
        let wrap
        let content
    
        afterUpdate(() => {
            const vslot = wrap.querySelector('#vslot')
            vslot.parentNode.replaceChild(content, vslot)
        })
    </script>
    
    <div bind:this={wrap}>
        {@html prefix + '<span id="vslot"></span>' + suffix}
    </div>
    
    <div bind:this={content}>
        <slot />
    </div>
    

    你会这样消费它:

    <Wrapper {prefix} {suffix}>
        <MyComponent />
    </Wrapper>
    

    REPL

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-28
      • 2018-12-01
      • 2015-07-15
      • 2016-06-30
      • 2013-11-29
      • 1970-01-01
      • 1970-01-01
      • 2019-07-26
      相关资源
      最近更新 更多