【问题标题】:Dynamically substitute Blazor component in HTML string在 HTML 字符串中动态替换 Blazor 组件
【发布时间】:2020-06-05 15:57:31
【问题描述】:

我想在我从服务接收的一些 HTML 文本中动态替换 Blazor 客户端组件。

例如,假设我收到以下字符串:

string htmlText = @"
<h1>Heading with {my component} inside it</h1>
";

我想用组件MyComponent 替换大括号内的所有文本,该组件接受参数Text 并呈现为&lt;em&gt;@Text&lt;/em&gt;

最后我想要得到的是:

<h1>Heading with <em>my component</em> inside it</h1>

我得到的最接近的方法是将字符串拆分为 HTML 部分和应替换为组件的部分(如:SplitText = htmlText.Split('{', '}');),然后在 Blazor 页面内的 for 循环中呈现它们:

@for (int i = 0; i < SplitText.Length; i++)
{
    if (i % 2 == 0)
    {
        @((MarkupString)SplitText[i])
    }
    else
    {
        <MyComponent Text="@SplitText[i]" />
    }
}

然而,这在 Chrome 中呈现为:

<h1>Heading with </h1>
<em>my component</em>
inside it

我也尝试使用RenderFragment,但最终得到了类似的结果。

编辑:

我将添加一些上下文来澄清我正在尝试做的事情。也可能有一些我没有想到的更好的方法,也许解释一下这样做的目的可以帮助有人为我指明一个更好的方向。

这旨在构建一个 Web 应用程序,用户可以在其中使用将输出 HTML(或 Markdown)的富编辑器编写自己的笔记(某种程度)。编辑器还将允许插入一些特殊标签以链接到他们编写的其他笔记。这些是示例中的大括号。文本将存储在数据库中并事先进行验证,因此无需处理语法错误(例如大括号内的 HTML 标记或嵌套的大括号)。当文本将被渲染时,特殊标签应该被相关组件替换,该组件生成链接并处理更多功能(例如,在鼠标悬停时弹出注释的预览)。因此,这将比仅添加 &lt;em&gt; 标记更复杂,如示例中所示。

我认为这可以通过 JavaScript 轻松完成,但首先我想看看是否可以使用纯 Blazor 来完成,因为它是一个非常有趣的新框架。

【问题讨论】:

  • @HenkHolterman 这不仅仅是一个标题,主要是带有格式的段落。不会有像你的例子那样奇怪的东西,因为文本将被验证。我在问题中添加了一些上下文,可能应该从一开始就这样做,抱歉。
  • 如果你有解决方案请告诉我
  • 有趣的想法,如果你有解决方案请告诉我。

标签: c# dynamic blazor blazor-client-side


【解决方案1】:

使用 MarkupString 有点棘手,因为 Blazor 引擎会自动关闭标签,并忽略没有相关开始标签的结束标签。这就是您获得上面看到的输出的方式。

由于服务提供包含标签的字符串,您可以将其与内部文本一起提供给组件,并执行一些智能字符串工作以获取将正确呈现的标记字符串。

MyComponent.razor

@if (MarkupText != null )
{
    @((MarkupString)$"{FirstHalf}{InnerText}{SecondHalf}")
}

@code{

    [Parameter] public string MarkupText { get; set; }

    // Inner Text set with starting value, can be left blank if needed
    [Parameter] public string InnerText { get; set; } = "";

    public string FirstHalf => MarkupText.Substring(0, MarkupText.IndexOf("{"));
    public string SecondHalf => MarkupText.Substring(MarkupText.IndexOf("}") + 1);
}

然后将它与上面的 htmlText 一起使用:

<MyComponent MarkupText="@htmlText" InnerText="<em>Something</em>" />

这个的输出变成:

标题里面有东西

这是一个简单的版本,应该给你的想法,但关键是你想将标记字符串设置为一个连续的字符串,然后一次性将其转换为MarkupString,所以编译器放置标签正确。使用同样的方法,您可以扩展上述想法,进行一些非常繁重的字符串操作,并尽可能多地构建内容。

附带说明,如果服务可以只提供带花括号的文本而不提供标签,那么您也可以非常轻松地使用RenderFragment 概念构建嵌套组件,并且您可以更好地分离内容和表示.通过接收一个没有标签的字符串,然后像我展示的那样拆分它,您只需要一个外部组件来获取字符串,拆分它,并将第一和第二部分相应地放置在子组件周围,Blazor 会以您期望的方式呈现它,根本不需要 MarkupString。标签将位于外部组件中。不确定您对该服务输出有多少控制权,但这是需要考虑的事情。

【讨论】:

  • 感谢您的建议和对 MarkupString 问题的解释,我有一种感觉,就是这样。然而不幸的是,我认为这个解决方案不适合我的情况,因为组件呈现的 HTML 会比它更复杂,并且组件也需要能够处理事件。我忘了在我的问题中提到这一点,对不起。我已经对其进行了编辑并添加了一些上下文来阐明我想要实现的目标。
猜你喜欢
  • 1970-01-01
  • 2019-05-01
  • 2020-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-02
  • 2017-06-18
  • 1970-01-01
相关资源
最近更新 更多