将 Blazor 组件渲染到现有 div(Blazor 无权访问)

Posted

技术标签:

【中文标题】将 Blazor 组件渲染到现有 div(Blazor 无权访问)【英文标题】:Render Blazor component into existing div (that Blazor has no access to) 【发布时间】:2021-07-17 16:50:31 【问题描述】:

我将 Blazor Server 与 React 应用程序一起用于布局部分。

当 Blazor 启动时,它会调用 JSInterop 来启动 React 组件。 React 组件基本上在其布局中创建了一大堆元素(这些元素的 id 是通过初始调用提供的)。

我的问题是如何告诉 Blazor 将组件渲染到那些 div 占位符中?

我能够找到的主题似乎总是在 Blazor 中提供容器的 html 代码(然后使用渲染片段)。但在这种情况下,我只有占位符 id - Blazor 中不知道实际元素。

在代码下方(此处不使用 react 库,而是在 JS 中创建一个 div,这样它是一个更简洁的示例)。主要问题是在 JS 呈现 div 后调用的 *** 部分 - 我如何告诉 Blazor 确认该 div 元素,或告诉 Blazor 找到它,并将组件呈现到其中?

Index.razor

@page "/"
@using Microsoft.Extensions.Configuration
@inject IConfiguration Config
@inject IJSRuntime Jsr
@implements IDisposable

<div></div>

@code 

    private DotNetObjectReference<Index> objectReference;

    [JSInvokable]
    public void SuccessRender(object succes-s-rendermessage)
    
        // ***Here is where it should call the render function.***
    

    public override Task SetParametersAsync(ParameterView parameters)
    
        objectReference = DotNetObjectReference.Create(this);
        return base.SetParametersAsync(parameters);
    

    protected override async Task OnAfterRenderAsync(bool firstRender)
    
        if (firstRender)
        
            await Jsr.InvokeVoidAsync("Library.CreateDiv", "uuid1", objectReference);
        
        await base.OnAfterRenderAsync(firstRender);
    

    public void Dispose()
    
        objectReference?.Dispose();
    
    


这里是JS代码:

export function CreateDiv(id, dotNetObj) 
$("body").append("<div id='" + id + "'></div>");
dotNetObj.invokeMethodAsync('SuccessRender', true);


【问题讨论】:

如果没有看到您的原始代码,我们将不知道如何对您现有的代码库进行更改。请发minimal reproducible example,并详细说明需要修改的地方。 道歉 - 添加了代码。 因此,如果我做对了,您就是在使用 jQuery/React 创建一个 DOM,然后让 Blazor 将数据放入被操纵的 DOM 中。这种情况的问题在于谁拥有 DOM 的主版本。 Blazor 不知道您的 id div 的存在,所以它不能用它做任何事情。是什么促使您使用 React 创建布局? @MrCakaShaunCurtis 我正在尝试使用我非常喜欢的 react 的 flexlayout 库 (github.com/caplin/FlexLayout)。我在 Blazor 世界中没有找到任何干净的东西。我理解你的观点,但它暗示 Blazor 总是希望任何 JS 小部件成为最终组件,而没有任何嵌套在里面(至少从 Blazor 的角度来看)? Blazor 仍然是拥有根的那个。但随后 react 在占位符 div 内创建一个组件,然后在该组件内我想放置 Blazor 项目。 @klarC “混合”框架几乎是不可能的,因为每个人都想控制 DOM。您正在寻找的是您最喜欢的布局工具的 Blazorized 版本,它可能不存在,您想编写它。您可能必须做出选择。 【参考方案1】:

这不是一个答案,而是一些你显然想走这条路的信息。

实际上,您可以在一个页面上拥有多个根组件。

index.html

添加具有唯一 ID 的额外 div:

....
    <div id="app">Loading...</div>

    <div id="app1">Loading...</div>

    <div id="app2">Loading...</div>

    <div id="app3">Loading...</div>
....

程序.cs

添加以下内容:

...
    var builder = WebAssemblyHostBuilder.CreateDefault(args);
    builder.RootComponents.Add<App>("#app");
    builder.RootComponents.Add<SurveyPrompt>("#app1");
    builder.RootComponents.Add<SurveyPrompt>("#app2");
    builder.RootComponents.Add<SurveyPrompt>("#app3");
...

MainLayout.razor(或您自己的自定义布局设置)它被第一个组件使用App

@inherits LayoutComponentBase
@Body

启动它,你应该得到这个:

所有 id 都必须存在于启动页面中。每个人都可以注册管理服务并....

【讨论】:

非常感谢您的建议。你知道这是否也可以在组件内动态工作吗?这意味着一个新的根可以在一个组件中开始吗?例如,这将允许生成动态选项卡。 你不能在一个组件中启动一个新的根组件,但是如果你的意思是,我可以有一个占位符来动态加载组件吗?是的。

以上是关于将 Blazor 组件渲染到现有 div(Blazor 无权访问)的主要内容,如果未能解决你的问题,请参考以下文章

将服务器端 Blazor 添加到现有 MVC Core 应用程序

如何从 Blazor 中的另一个组件重新渲染一个组件?

使用参数渲染 Blazor 子组件

从 JavaScript 渲染 Blazor 组件 - 如何在组件渲染后从 JavaScript 更新 Blazor 组件参数

Blazor University (17)使用 RenderFragments 模板化组件

如何在没有 Javascript 的情况下将焦点设置到页面顶部?