发出真正“原始"的声音细长的 html [英] Emit truly "raw" html in Svelte

查看:23
本文介绍了发出真正“原始"的声音细长的 html的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从无头 CMS 接收原始 html 片段,我需要在 Sapper 应用程序中按原样呈现这些片段.

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

<!-- 按原样使用代码片段 -->{@html 前缀}<我的组件/>{@html 后缀}

请参阅 https://svelte.dev/repl/4c1bf80ae00e476587344b6065e7346e?version=3.19.1"1

然而,Svelte 期望用@html 呈现的每个项目都是自包含元素,并试图修复"常见错误.例如,它将向前缀代码段添加一个结束标记,将 <MyComponent/>-part 移出 p.

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

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

解决方案

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

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

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

...但也许它可以让你摆脱简单的情况.你是法官.

我的想法是用一个额外的元素来渲染完整的连接字符串(前缀 + 后缀),我可以抓取并替换一​​个已经由 Svelte 独立渲染的组件,在这个片段之外.

诀窍如下:

{@html 前缀 + '</span>'+ 后缀}

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

<div bind:this={wrap}>{@html 前缀 + '<span id="vslot"></span>'+ 后缀}

<div bind:this={content}><插槽/>

你会像这样消费它:

REPL

I'm receiving raw html snippets from a headless CMS that I need to render as-is in a Sapper application.

This also includes cases where I receive an opening tag and the corresponding closing tag as two pieces of HTML between which I add a Svelte component.

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

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

However, Svelte expects each item rendered with @html to be self contained element and tries to "fix" common errors. For example, it will add a closing tag to the prefix-snippet, moving the <MyComponent/>-part out of the p.

Is there a way to circumvent this behavior in general? Or more specifically - is it possible to surround rendered components with arbitrary raw HTML?

As a side node: this runs as a sapper app and the server side rendered version of the page does correctly emit the raw HTML. It's when the client side rendering kicks in that the behavior changes.

解决方案

Here's a wicked way...

DISCLAIMER Moving Svelte managed elements under its feet can't possibly be a good idea and I totally fail to appreciate what adverse side effects you might encounter next!

I especially recommend against using this in {#each} blocks, and especially keyed ones, since Svelte will want to reorder its elements and might be upset if they're not where it expects them in the DOM.

... but maybe it can get you unstuck for simple cases. You be the judge.

My idea is to render the full concatenated string (prefix + suffix) with an additional element I can grab and replace with a component already rendered independently by Svelte, outside of this fragment.

Here's the trick:

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

Here's an example component that implements the trick:

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

You would consume it like this:

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

REPL

这篇关于发出真正“原始"的声音细长的 html的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆