blazor
No sé si alguien quiere compilar dinámicamente algunas bibliotecas de componentes directamente en el navegador como yo . En lugar de NuGet
ver el efecto después de la referencia, y al usar los componentes de otras personas, puede ajustar dinámicamente algunos estilos de los componentes.
Por no hablar del comienzo del texto:
En este artículo, usaremos Masa
un componente proporcionado para implementar la compilación dinámica de github.com through-train y el entorno de ejecución se WebAssembly
ejecutará en él. ¿Por qué WebAssembly
no usarlo Server
? En primer lugar, debemos comprender los principios de ejecución de estos dos modos.
Ensamblaje web:
Blazor WebAssembly
SíBlazor WebAssembly
, para crear aplicaciones web interactivas del lado del cliente mediante .NET.Blazor WebAssembly
Utilice estándares web abiertos sin complementos ni recompilación de código en otros idiomas.Blazor WebAssembly
Funciona con todos los navegadores web modernos, incluidos los navegadores móviles.
Servidor:
-
Blazor Server
ASP.NET Core
La aplicación admite el alojamiento de componentes de Razor en el servidor. Las actualizaciones de la interfaz de usuario se pueden gestionar a través de una conexión SignalR .El tiempo de ejecución permanece en el servidor y procesa:
- Ejecute el código C# de la aplicación.
- Envía eventos de UI desde el navegador al servidor.
- Aplica actualizaciones de la interfaz de usuario a los componentes renderizados que devuelve el servidor.
Dado que la compilación es completamente operable, existen problemas de seguridad. En el modo Servidor, el entorno de compilación del usuario es el entorno del servidor, por lo que el usuario puede compilar dinámicamente el código para lograr la seguridad de intrusión operativa. El problema es muy grave. En serio, es no se recomienda utilizar la compilación dinámica en el servidor
Implementación Vamos a crear un proyecto WebAssembly vacío
mkdir compileRazor
cd compileRazor
dotnet new blazorwasm-empty
Use vs para abrir el proyecto y agregue Masa.Blazor.Extensions.Languages.Razor , agregue el siguiente código al archivo del proyecto
<PackageReference Include="Masa.Blazor.Extensions.Languages.Razor" Version="0.0.1" />
Modificar Program.cs
el código del archivo.
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using compileRazor;
using Masa.Blazor.Extensions.Languages.Razor;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
var app = builder.Build();
// 初始化RazorCompile
RazorCompile.Initialized(await GetReference(app.Services), await GetRazorExtension());
await app.RunAsync();
// 添加程序集引用
async Task<List<PortableExecutableReference>?> GetReference(IServiceProvider services)
{
#region WebAsembly
// need to add Service
var httpClient = services.GetService<HttpClient>();
var portableExecutableReferences = new List<PortableExecutableReference>();
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
//你需要通过网络获取程序集,应为无法通过程序集目录获取
var stream = await httpClient!.GetStreamAsync($"_framework/{assembly.GetName().Name}.dll");
if (stream.Length > 0)
{
portableExecutableReferences?.Add(MetadataReference.CreateFromStream(stream));
}
}
catch (Exception e) // There may be a 404
{
Console.WriteLine(e.Message);
}
}
#endregion
// 由于WebAssembly和Server返回portableexecutablerreference机制不同,需要分开处理
return portableExecutableReferences;
}
async Task<List<RazorExtension>> GetRazorExtension()
{
var razorExtension = new List<RazorExtension>();
foreach (var asm in typeof(Program).Assembly.GetReferencedAssemblies())
{
razorExtension.Add(new AssemblyExtension(asm.FullName, AppDomain.CurrentDomain.Load(asm.FullName)));
}
return razorExtension;
}
Pages\Index.razor
código modificado
@page "/"
@using Masa.Blazor.Extensions.Languages.Razor;
<button class="button" @onclick="Run">刷新</button>
<div class="input-container">
<textarea @bind="Code" type="text" class="input-box" placeholder="请输入执行代码" >
</textarea>
</div>
@if (ComponentType != null)
{
<DynamicComponent Type="ComponentType"></DynamicComponent>
}
@code{
private string Code = @"<body>
<div id='app'>
<header>
<h1>Doctor Who™ Episode Database</h1>
</header>
<nav>
<a href='main-list'>Main Episode List</a>
<a href='search'>Search</a>
<a href='new'>Add Episode</a>
</nav>
<h2>Episodes</h2>
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<footer>
Doctor Who is a registered trademark of the BBC.
https://www.doctorwho.tv/
</footer>
</div>
</body>";
private Type? ComponentType;
private void Run()
{
ComponentType = RazorCompile.CompileToType(new CompileRazorOptions()
{
Code = Code // TODO: 在WebAssembly下保证ConcurrentBuild是false 因为Webassembly不支持多线程
});
StateHasChanged();
}
}
<style>
.button{
width: 100%;
font-size: 22px;
background-color: cornflowerblue;
border: 0px;
margin: 5px;
border-radius: 5px;
height: 40px;
}
.input-container {
width: 500px;
margin: 0 auto;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
.input-box {
width: 100%;
height: 100px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 14px;
}
</style>
Entonces el efecto de iniciar el programa es como se muestra en la figura:
La primera compilación será más lenta WebAssembly
y puede atascarse debido a problemas de la computadora. Si necesita mejorar la eficiencia del desarrollo, puede usar la depuración del servidor. La depuración en el servidor es WebAssembly
mucho más rápida que eso y WebAssembly
no ha hecho mucho, por lo que el rendimiento no será muy bueno.
Compartir desde token
Grupo técnico de intercambio: 737776595
Blazor UI
Recomiende un componente súper fácil de usar Protocolo de código abierto MASA Blazor , MIT
el uso comercial no es ningún problema