You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Razor页面A的组件B中引用页面C的组件D或HTML元素

跨Razor页面复用组件/HTML内容的解决方案

一、当D是Razor组件时的实现

Blazor中不同页面的组件属于独立组件树,无法直接引用已渲染的组件实例,核心思路是复用D组件逻辑+共享C页面的数据,替代直接引用实例。

1. 实现共享状态服务

创建范围服务存储C页面的数据,让A、C页面共享同一数据源:

// Services/SharedDataService.cs
public class SharedDataService
{
    public DComponentData CurrentData { get; set; }
    public event Action OnDataUpdated;

    public void UpdateData(DComponentData newData)
    {
        CurrentData = newData;
        OnDataUpdated?.Invoke();
    }
}

// Models/DComponentData.cs
public class DComponentData
{
    // 定义D组件所需数据字段
    public string Title { get; set; }
    public string Content { get; set; }
}

在Program.cs注册服务:

builder.Services.AddScoped<SharedDataService>();

2. 修改C页面与D组件

C页面初始化或更新数据时,同步到共享服务:

<!-- Pages/C.cshtml -->
@inject SharedDataService DataService
@page "/c"

<DComponent />

@code {
    protected override void OnInitialized()
    {
        // 模拟C页面初始化数据
        var initialData = new DComponentData
        {
            Title = "来自C页面的标题",
            Content = "来自C页面的内容"
        };
        DataService.UpdateData(initialData);
        base.OnInitialized();
    }

    // 若C页面数据更新,同步到共享服务
    private void SyncPageData()
    {
        // 假设D组件有暴露获取当前数据的方法
        var updatedData = new DComponentData { /* 从D组件或页面获取最新数据 */ };
        DataService.UpdateData(updatedData);
    }
}

D组件从共享服务获取数据并监听更新:

<!-- Components/DComponent.razor -->
@inject SharedDataService DataService

<div class="d-component">
    <h3>@DataService.CurrentData?.Title</h3>
    <p>@DataService.CurrentData?.Content</p>
</div>

@code {
    protected override void OnInitialized()
    {
        DataService.OnDataUpdated += StateHasChanged;
        base.OnInitialized();
    }

    public void Dispose()
    {
        DataService.OnDataUpdated -= StateHasChanged;
    }
}

3. 在A页面的B组件中复用D

B组件直接引用D组件,自动共享C页面的数据:

<!-- Components/BComponent.razor -->
<h4>B组件容器</h4>
<DComponent />

A页面引用B组件即可:

<!-- Pages/A.cshtml -->
@page "/a"

<BComponent />

原级联参数失效原因

级联参数仅能在同一组件树内传递,跨页面组件属于独立树,因此无法生效,必须用共享状态服务。


二、当D是HTML div时的实现

方式1:SignalR实时同步内容

适合需要实时同步的场景:

  1. 创建SignalR Hub:
// Hubs/ContentSyncHub.cs
public class ContentSyncHub : Hub
{
    public async Task SyncDivContent(string content)
    {
        await Clients.Others.SendAsync("ReceiveDivContent", content);
    }
}

在Program.cs注册:

builder.Services.AddSignalR();
app.MapHub<ContentSyncHub>("/contentSyncHub");
  1. C页面监听div变化并推送内容:
<!-- Pages/C.cshtml -->
<div id="targetDiv" contenteditable="true">初始内容</div>

<script>
    const connection = new signalR.HubConnectionBuilder()
        .withUrl("/contentSyncHub")
        .build();

    connection.start().catch(err => console.error(err.toString()));

    const targetDiv = document.getElementById('targetDiv');
    targetDiv.addEventListener('input', () => {
        connection.invoke("SyncDivContent", targetDiv.innerHTML)
            .catch(err => console.error(err.toString()));
    });
</script>
  1. B组件接收并显示内容:
<!-- Components/BComponent.razor -->
<div id="divContainer"></div>

@code {
    [Inject] private IJSRuntime JSRuntime { get; set; }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JSRuntime.InvokeVoidAsync("setupContentSync");
        }
        await base.OnAfterRenderAsync(firstRender);
    }
}

添加全局JS(wwwroot/js/sync.js):

window.setupContentSync = function() {
    const connection = new signalR.HubConnectionBuilder()
        .withUrl("/contentSyncHub")
        .build();

    connection.on("ReceiveDivContent", function(content) {
        document.getElementById('divContainer').innerHTML = content;
    });

    connection.start().catch(err => console.error(err.toString()));
}

方式2:API接口获取内容

适合无需实时同步的场景:

  1. 创建API接口:
// Controllers/DivContentController.cs
[ApiController]
[Route("api/div-content")]
public class DivContentController : ControllerBase
{
    private static string _divContent = "初始内容";

    [HttpGet]
    public IActionResult GetContent() => Ok(_divContent);

    [HttpPost]
    public IActionResult UpdateContent([FromBody] string content)
    {
        _divContent = content;
        return Ok();
    }
}
  1. C页面保存div内容到API:
<!-- Pages/C.cshtml -->
<div id="targetDiv" contenteditable="true">初始内容</div>

<script>
    const targetDiv = document.getElementById('targetDiv');
    targetDiv.addEventListener('blur', async () => {
        await fetch('/api/div-content', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(targetDiv.innerHTML)
        });
    });
</script>
  1. B组件获取并显示内容:
<!-- Components/BComponent.razor -->
<div id="divContainer">@divContent</div>

@code {
    private string divContent;
    [Inject] private HttpClient Http { get; set; }

    protected override async Task OnInitializedAsync()
    {
        divContent = await Http.GetStringAsync("/api/div-content");
    }

    // 可选:定时刷新内容
    private async Task RefreshContent()
    {
        divContent = await Http.GetStringAsync("/api/div-content");
        StateHasChanged();
    }
}

原方案失败原因

  • iframe方案:iframe的视口限制会导致模态框显示异常,属于iframe固有问题,修复复杂度极高。
  • jQuery替换HTML:Blazor会维护自身组件树状态,手动修改DOM会破坏Blazor运行环境,触发"Blazor is already running"错误。

内容的提问来源于stack exchange,提问作者coderLane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 02:52:52