Blazor - 多 bootstrap / 多租户
Blazor - Multi bootstrap / Multitenant
有没有更优雅的方式将 2 bootsraps/css 混合在一个项目中?
我有一个 Blazor 应用程序(服务器预呈现),它有 2 个区域:
- 客户的最终用户(订购服务)
- 管理员(股票管理、价格...)- 仅供管理员用户使用
我已经使用 bootstrap 5 开发了管理部分(实际上我使用了 MudBlazor 和它自己的 bootstrap)。
我需要网站的“最终用户”部分,将在其中使用完全不同的 bootstrap ( https://themes.getbootstrap.com/product/space-multipurpose-responsive-template/ )。
我可以将 2 个网站拆分为 2 个不同的“网络项目”,但客户更喜欢使用单一应用程序,我没有找到如何实现此目的的记录示例,因此我已将 _Host.cshtml 更改为“catch " 管理页面(并将它们指向页面 Admin.cshtml
)
@page "/"
@namespace MultiAreaDemo.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = null;
}
@if (Request.Query["admin"].FirstOrDefault() == "1")
{
Html.RenderPartial("Admin.cshtml", null, ViewData);
return;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MultiAreaDemo - End user</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/space-enduser/bootstrap.min.css" />
<link href="MultiAreaDemo.styles.css" rel="stylesheet" />
</head>
.....
并创建了 Admin.cshtml 页面(指向“admin”bootstrap css):
@page "/admin"
@namespace MultiAreaDemo.Pages.Admin
@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>MultiAreaDemo - ADMIN </title>
<base href="~/" />
<link rel="stylesheet" href="css/admin/bootstrap.min.css" />
</head>
<body>
<component type="typeof(App)" render-mode="ServerPrerendered" />
<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>
所有“admin”页面都需要以“admin”为前缀。例如:
@page "/admin"
<h3>AdminHome</h3>
....
因此页面 https://localhost:44398/admin 使用 css/admin/bootstrap.min.css
而 https://localhost:44398/ 使用 css/bootstrap/space-enduser/bootstrap.min.css
希望对您有所帮助。如果有人知道更优雅的方式,我将不胜感激。
您可以切换 CSS - 以及 header 中的几乎任何其他内容 - 如下所示:
如下定义您的 Css link 给它一个 id:
<link id="dynamicCssLink" rel="stylesheet" href="/css/site.css" />
定义一些包含在您网站中的 JS 代码 - 我通常使用 site.js:
window.DynamicCss = {
setCss: function (elementId, url) {
var link = document.getElementById(elementId);
if (link === undefined) {
link = document.createElement(elementId);
link.id = elementId;
document.head.insertBefore(link, document.head.firstChild);
link.type = 'text/css';
link.rel = 'stylesheet';
}
link.href = url;
return true;
}
}
为 JS 互操作代码定义一个 Class:
public class InteropLibrary
{
protected IJSRuntime JSRuntime { get; }
public InteropLibrary(IJSRuntime jsRuntime)
=> JSRuntime = jsRuntime;
public ValueTask<bool> SetDynamicCss(string elementId, string url)
=> JSRuntime.InvokeAsync<bool>("DynamicCss.setCss", elementId, url);
}
在服务中注册
builder.Services.AddScoped<InteropLibrary>();
创建替代方案site.css
。我的 - site-black.css - 看起来像这样:
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
background-color:black !important;
color: white !important;
}
....
我的测试 Index
页面如下所示:
@page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
<div class="m-2">
<button class="btn @this.buttonColour" @onclick="SwitchCSS">@this.buttonLabel</button>
</div>
@code {
[Inject] private InteropLibrary? interopLibrary { get; set; }
private bool isDark;
private string css => isDark ? "/css/site-black.css" : "/css/site.css";
private string buttonLabel => isDark ? "Switch To Light" : "Switch To Dark" ;
private string buttonColour => isDark ? "btn-light" : "btn-dark" ;
private async Task SwitchCSS()
{
this.isDark = !this.isDark;
await interopLibrary!.SetDynamicCss("dynamiccsslink", this.css);
}
}
在索引页面和计数器页面之间切换样式表的示例实现
Layout.razor:
@inherits LayoutComponentBase
..... Mark-up
@code {
[Inject] private InteropLibrary? interopLibrary { get; set; }
private string _stylesheet = "/css/site.css";
protected async override Task OnAfterRenderAsync(bool firstRender)
{
await interopLibrary!.SetDynamicCss("dynamiccsslink", _stylesheet);
await base.OnInitializedAsync();
}
}
深色Layout.razor
@inherits LayoutComponentBase
..... Mark-up
@code {
[Inject] private InteropLibrary? interopLibrary { get; set; }
private string _stylesheet = "/css/dark-site.css";
protected async override Task OnAfterRenderAsync(bool firstRender)
{
await interopLibrary!.SetDynamicCss("dynamiccsslink", _stylesheet);
await base.OnInitializedAsync();
}
}
索引
@page "/"
@layout MainLayout
<PageTitle>Index</PageTitle>
.....
计数器
@page "/counter"
@layout DarkLayout
<PageTitle>Counter</PageTitle>
....
有没有更优雅的方式将 2 bootsraps/css 混合在一个项目中?
我有一个 Blazor 应用程序(服务器预呈现),它有 2 个区域:
- 客户的最终用户(订购服务)
- 管理员(股票管理、价格...)- 仅供管理员用户使用
我已经使用 bootstrap 5 开发了管理部分(实际上我使用了 MudBlazor 和它自己的 bootstrap)。
我需要网站的“最终用户”部分,将在其中使用完全不同的 bootstrap ( https://themes.getbootstrap.com/product/space-multipurpose-responsive-template/ )。
我可以将 2 个网站拆分为 2 个不同的“网络项目”,但客户更喜欢使用单一应用程序,我没有找到如何实现此目的的记录示例,因此我已将 _Host.cshtml 更改为“catch " 管理页面(并将它们指向页面 Admin.cshtml
)
@page "/"
@namespace MultiAreaDemo.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = null;
}
@if (Request.Query["admin"].FirstOrDefault() == "1")
{
Html.RenderPartial("Admin.cshtml", null, ViewData);
return;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MultiAreaDemo - End user</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/space-enduser/bootstrap.min.css" />
<link href="MultiAreaDemo.styles.css" rel="stylesheet" />
</head>
.....
并创建了 Admin.cshtml 页面(指向“admin”bootstrap css):
@page "/admin"
@namespace MultiAreaDemo.Pages.Admin
@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>MultiAreaDemo - ADMIN </title>
<base href="~/" />
<link rel="stylesheet" href="css/admin/bootstrap.min.css" />
</head>
<body>
<component type="typeof(App)" render-mode="ServerPrerendered" />
<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>
所有“admin”页面都需要以“admin”为前缀。例如:
@page "/admin"
<h3>AdminHome</h3>
....
因此页面 https://localhost:44398/admin 使用 css/admin/bootstrap.min.css
而 https://localhost:44398/ 使用 css/bootstrap/space-enduser/bootstrap.min.css
希望对您有所帮助。如果有人知道更优雅的方式,我将不胜感激。
您可以切换 CSS - 以及 header 中的几乎任何其他内容 - 如下所示:
如下定义您的 Css link 给它一个 id:
<link id="dynamicCssLink" rel="stylesheet" href="/css/site.css" />
定义一些包含在您网站中的 JS 代码 - 我通常使用 site.js:
window.DynamicCss = {
setCss: function (elementId, url) {
var link = document.getElementById(elementId);
if (link === undefined) {
link = document.createElement(elementId);
link.id = elementId;
document.head.insertBefore(link, document.head.firstChild);
link.type = 'text/css';
link.rel = 'stylesheet';
}
link.href = url;
return true;
}
}
为 JS 互操作代码定义一个 Class:
public class InteropLibrary
{
protected IJSRuntime JSRuntime { get; }
public InteropLibrary(IJSRuntime jsRuntime)
=> JSRuntime = jsRuntime;
public ValueTask<bool> SetDynamicCss(string elementId, string url)
=> JSRuntime.InvokeAsync<bool>("DynamicCss.setCss", elementId, url);
}
在服务中注册
builder.Services.AddScoped<InteropLibrary>();
创建替代方案site.css
。我的 - site-black.css - 看起来像这样:
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
background-color:black !important;
color: white !important;
}
....
我的测试 Index
页面如下所示:
@page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
<div class="m-2">
<button class="btn @this.buttonColour" @onclick="SwitchCSS">@this.buttonLabel</button>
</div>
@code {
[Inject] private InteropLibrary? interopLibrary { get; set; }
private bool isDark;
private string css => isDark ? "/css/site-black.css" : "/css/site.css";
private string buttonLabel => isDark ? "Switch To Light" : "Switch To Dark" ;
private string buttonColour => isDark ? "btn-light" : "btn-dark" ;
private async Task SwitchCSS()
{
this.isDark = !this.isDark;
await interopLibrary!.SetDynamicCss("dynamiccsslink", this.css);
}
}
在索引页面和计数器页面之间切换样式表的示例实现
Layout.razor:
@inherits LayoutComponentBase
..... Mark-up
@code {
[Inject] private InteropLibrary? interopLibrary { get; set; }
private string _stylesheet = "/css/site.css";
protected async override Task OnAfterRenderAsync(bool firstRender)
{
await interopLibrary!.SetDynamicCss("dynamiccsslink", _stylesheet);
await base.OnInitializedAsync();
}
}
深色Layout.razor
@inherits LayoutComponentBase
..... Mark-up
@code {
[Inject] private InteropLibrary? interopLibrary { get; set; }
private string _stylesheet = "/css/dark-site.css";
protected async override Task OnAfterRenderAsync(bool firstRender)
{
await interopLibrary!.SetDynamicCss("dynamiccsslink", _stylesheet);
await base.OnInitializedAsync();
}
}
索引
@page "/"
@layout MainLayout
<PageTitle>Index</PageTitle>
.....
计数器
@page "/counter"
@layout DarkLayout
<PageTitle>Counter</PageTitle>
....