gpt4 book ai didi

asp.net-core - 在用户内容中放置 Blazor 组件

转载 作者:行者123 更新时间:2023-12-04 08:37:31 27 4
gpt4 key购买 nike

我需要在用户提供的内容中动态放置 Blazor 组件。本质上,该组件应该使用一些 UI 元素扩展用户提供的标记。
假设用户提供了一些可以在其中包含“greeting-container”元素的内容,并且组件应该在该元素中插入一个问候按钮。
我目前的解决方案是调用一个 JavaScript 函数来移动 OnAfterRenderAsync 中的 DOM 元素。 (完整代码如下)。它似乎工作正常,但在 Blazor 中似乎不鼓励操作 DOM 元素,因为它会影响差异算法。所以我有几个问题:

  • 像这样移动 DOM 元素有多糟糕?它是否会导致性能问题、功能问题或一些未定义的行为?
  • 有没有更好的方法可以在不使用 JavaScript 的情况下实现相同的结果?我正在考虑使用 RenderTreeBuilder为此,但似乎它可能不是为此目的而设计的,因为建议使用硬编码的序列号,这在处理编译时未知的动态内容时似乎是不可能的。

  • 当前解决方案代码:
    Greeter.razor
    @page "/greeter"

    @inject IJSRuntime JSRuntime;

    <div>
    @((MarkupString)UserContentMarkup)
    <div id="greeting">
    <button @onclick="ToggleGreeting">Toggle greeting</button>
    @if (isGreetingVisible) {
    <p>Hello, @Name!</p>
    }
    </div>
    </div>

    @code {
    [Parameter]
    public string UserContentMarkup { get; set; }

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

    private bool isGreetingVisible;

    private void ToggleGreeting()
    {
    isGreetingVisible = !isGreetingVisible;
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
    await JSRuntime.InvokeVoidAsync("moveGreetingToContainer");
    }
    }
    _Host.cshtml
    window.moveGreetingToContainer = () => {
    var greeting = document.getElementById("greeting");

    var container = document.getElementById("greeting-container");

    container.appendChild(greeting);
    }
    UserContentTest.razor
    @page "/userContentTest"

    @inject IJSRuntime JSRuntime;

    <h3>Testing user content</h3>

    <Greeter UserContentMarkup=@userContentMarkup Name="John"></Greeter>

    @code {
    private string userContentMarkup = "Some <b>HTML</b> text followed by greeting <div id='greeting-container'></div> and <i>more</i> text";
    }
    预期结果(点击“切换问候语”后):
    <div>
    Some <b>HTML</b> text followed by greeting
    <div id="greeting-container">
    <div id="greeting">
    <button>Toggle greeting</button>
    <p>Hello, John!</p>
    </div>
    </div> and <i>more</i> text
    </div>

    最佳答案

    好问题 - 是的,使用 JS 移动 dom 元素非常糟糕,因为 Blazor 没有看到您对 dom 所做的更改。
    您可以做的是切换到使用 RenderFragment更具体地说 RenderFragment<RenderFragment>这是将提供更多标记作为参数的标记。
    在第二行,我调用 UserContentMarkup 方法(它是一个 RenderFragment<RenderFragment>)并传入 <div id=greeting>内容为context范围。
    注意:它被包裹在 <text> 中元素,它实际上是将 HTML 嵌入到 Razor 文件中的 C# 中的一种方式。它不会呈现 <text>元素到页面。
    Greeter.razor

    <div>
    @UserContentMarkup(
    @<text>
    <div id="greeting">
    <button @onclick="ToggleGreeting">Toggle greeting</button>
    @if (isGreetingVisible) {
    <p>Hello, @Name!</p>
    }
    </div>
    </text>
    )
    </div>
    @code {
    [Parameter]
    public RenderFragment<RenderFragment> UserContentMarkup { get; set; }

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

    private bool isGreetingVisible;

    private void ToggleGreeting()
    {
    isGreetingVisible = !isGreetingVisible;
    }
    }
    UserContentTest.razor
    在这里你可以看到两种使用 Greeter 的方式 - 使用页面中的标记,或者使用 code方法。
    <h3>Testing user content</h3>

    @* Using markup to supply user content - @context is where the button goes *@
    <Greeter Name="John">
    <UserContentMarkup>
    Some <b>HTML</b> text followed by greeting
    <div id='greeting-container'>@context</div> and <i>more</i> text
    </UserContentMarkup>
    </Greeter>

    @* Using a method to supply the user content - @context is where the button goes *@
    <Greeter Name="John" UserContentMarkup=@userContent />
    code方法可能会令人困惑 - 它是 RenderFragment<RenderFragment>这意味着它必须是一个接受 RenderFragment 的方法作为它的唯一参数,并返回 RenderFragment - RenderFragment在这种情况下返回的是标记包装在 <text> 中说清楚它是标记。
    @code
    {
    RenderFragment<RenderFragment> userContent
    => context => @<text>Some stuff @context more stuff</text>;
    }
    在这里试试: https://blazorrepl.com/repl/QuPPaMEu34yA5KSl40

    关于asp.net-core - 在用户内容中放置 Blazor 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64731542/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com