我们可以在常规非 Blazor HTML 页面中将 Blazor 组件用作 Web 组件吗?

问题描述 投票:0回答:3

我们可以将 Blazor 组件渲染为独立的 DOM 片段,或者以其他方式将其用作普通 HTML/JS 页面中的标准 Web 组件吗?

从 Blazor 架构的角度来看,这可能是一个天真的问题。到目前为止,我还不是 Blazor 专家,但我认为它对于遗留 Web 应用程序的增量“棕地”现代化来说可能是一种有用的技术。我很惊讶这似乎没有得到官方支持。

为了说明这一点,请考虑这个简单的 Web 组件示例,它呈现一个自定义元素

<date-info>
:

// define a custom web component
customElements.define("date-info", class DateInfo extends HTMLElement {
  constructor() {
    super();
    // create an "open" (vs "closed") shadow DOM, 
    // i.e., accessible to the outside JavaScript
    this.attachShadow({ mode: "open" });
  }

  async connectedCallback() {
    console.log(`${this.constructor.name}.${this.connectedCallback.name} called`);

    // get the content from the server, 
    // this could be a Blazor component markup
    try {
      const response = await fetch("https://worldtimeapi.org/api/ip");
      const data = await response.json();
      const content = new Date(data.utc_datetime).toString();
      this.shadowRoot.innerHTML = `<span>${content}</span>`;
    }
    catch(e) {
      console.error(e);
      const info = document.createTextNode(e.message); 
      this.shadowRoot.appendChild(info);
    }
  }
});
<!-- use the web component --> 
<p>Current time: <date-info/></p>

现在,我不想获取

https://worldtimeapi.org/api/ip
,而是想获取并呈现 Blazor/服务器组件的分离标记,例如:

@* this is a Blazor component *@
<p>@(DateTime.Now)</p>

此外,我希望此标记保持功能性和动态性,即此 Blazor 组件的客户端 DOM 事件和服务器端更新将通过包装 Web 组件的生命周期进一步双向传播。

当然可以将其设为 Blazor

@page
并将其加载到
iframe
中,但我更希望将其渲染为外部页面 DOM 的一部分。

到目前为止,我遇到过这个:

c# html .net blazor web-component
3个回答
8
投票

MS 已解决此限制,但该解决方案需要 .Net 6。

https://github.com/aspnet/AspLabs/tree/a5137f28510dd3673a28fa1c29e1cf7415ecac2c/src/BlazorCustomElements

这是由史蒂夫·桑德森本人完成的。

更新 11/8/24: BlazorCustomElements 项目已添加到 .NET 7 中(随后从该 AspLabs 存储库中删除)。 这里是当前的微软文档,介绍如何在 .NET 8 中配置它们。


3
投票

与此同时,您可以将旧的 cshtml 与 razor 组件混合使用。 我使用这种方法在两个系统之间保持相同的图形布局
举个例子,以下文件是 _

Layout.cshtml

Identity 使用。 我通过静态渲染使用了各种 Blazor 组件:
@using Microsoft.AspNetCore.Hosting @using Microsoft.AspNetCore.Mvc.ViewEngines @inject IWebHostEnvironment Environment @inject ICompositeViewEngine Engine @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @using Project.Server.Shared <!DOCTYPE html> <html> <head> <component type="typeof(MainLayoutHead)" render-mode="Static" /> </head> <body> <app> <div class="container main"> <component type="typeof(MainLayoutTopImages)" render-mode="Static" /> <div class="row navmenu-row"> <div class="col-md-12 bg-dark navmenu-col"> <component type="typeof(NavMenu)" render-mode="Static" /> </div> </div> <div class="row content pt-4 pb-0 mt-0"> <div class="col-md-12"> <div class="row"> <div class="col-md-12"> @*Required for GDPR.*@ <partial name="_CookieConsentPartial" /> </div> </div> <div class="row body-row"> <div class="col-md-12 body-col"> @RenderBody() </div> </div> </div> </div> <component type="typeof(MainLayoutFooter)" render-mode="Static" /> </div> </app> <script src="~/Identity/lib/jquery/dist/jquery.min.js"></script> <script src="~/Identity/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script> <script src="~/Identity/js/site.js" asp-append-version="true"></script> @RenderSection("Scripts", required: false) </body> </html>

 
MainLayoutHead

MainLayoutFooter
NavMenu
是常规 Blazor 组件。
    


2
投票
Page

自定义属性的组件。

此设置的问题在于,一旦刷新页面,就会重新启动三个组件,并且会丢失任何范围内的数据。

@page "/test" @namespace StackOverflow.Answers.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @{ Layout = null; } <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>StackOverflow.Answers</title> <base href="~/" /> <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" /> <link href="css/site.css" rel="stylesheet" /> <link href="StackOverflow.Answers.styles.css" rel="stylesheet" /> </head> <body> <div class="m-2 p-s bg-light"> <h3>A Normal Razor Page</h3> <p> Lots of server side rendered junk </p> <component type="typeof(StackOverflow.Answers.Shared.SurveyPrompt)" render-mode="ServerPrerendered" /> </div> <div class="m-2 p-s bg-info"> <h3>A Normal Header</h3> <p> Lots More server side rendered junk </p> <component type="typeof(StackOverflow.Answers.Pages.Counter)" render-mode="ServerPrerendered" /> </div> <div class="m-2 p-s bg-light"> <h3>A Normal Header</h3> <p> Lots More server side rendered junk </p> <component type="typeof(StackOverflow.Answers.Pages.Counter)" render-mode="ServerPrerendered" /> </div> <div class="m-2 p-s bg-light"> <h3>Yet Another Normal Header</h3> <p> Lots More server side rendered junk </p> <component type="typeof(StackOverflow.Answers.Pages.FetchData)" render-mode="ServerPrerendered" /> </div> <div class="m-2 p-s bg-light"> <h3>Yet Another Normal Header</h3> <p> Lots More server side rendered junk </p> <component type="typeof(StackOverflow.Answers.Pages.FetchData)" render-mode="ServerPrerendered" /> </div> <div id="blazor-error-ui"> <environment include="Staging,Production"> An error has occurred. This application may no longer respond until reloaded. </environment> <environment include="Development"> An unhandled exception has occurred. See browser dev tools for details. </environment> <a href="" class="reload">Reload</a> <a class="dismiss">🗙</a> </div> <script src="_framework/blazor.server.js"></script> </body> </html>

	
© www.soinside.com 2019 - 2024. All rights reserved.