如何在没有第三方库的情况下创建对话框。
我必须使用最少量的js,因为新的HTML5
<dialog...
元素只能通过
.showModal()
而不是通过操作属性来以对话框模式打开。
wwwroot/scripts/dialogJsInteropt.js
export function showDialog(element, parm) {
return element.showModal();
}
export function closeDialog(element, parm) {
return element.close();
}
Dialog.razor
<CascadingValue Value=@this IsFixed=true >
<dialog @ref="@dialogElement" @attributes=@CapturedAttributes>
@if(visible)
{
@ChildContent
}
</dialog>
</CascadingValue>
Dialog.razor.cs
public partial class Dialog : ComponentBase, IAsyncDisposable
{
private readonly Lazy<Task<IJSObjectReference>> moduleTask;
private ElementReference dialogElement;
private bool visible = false;
public Dialog()
{
moduleTask = new(() => jsRuntime.InvokeAsync<IJSObjectReference>(
identifier: "import",
args: "./scripts/dialogJsInterop.js")
.AsTask());
}
[Inject]
private IJSRuntime jsRuntime { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> CapturedAttributes { get; set; }
public async ValueTask ShowDialogAsync()
{
var module = await moduleTask.Value;
await module.InvokeVoidAsync("showDialog", dialogElement);
visible = true;
}
public async ValueTask CloseDialogAsync()
{
var module = await moduleTask.Value;
await module.InvokeVoidAsync("closeDialog", dialogElement);
visible = false;
}
public async ValueTask DisposeAsync()
{
if (moduleTask.IsValueCreated)
{
var module = await moduleTask.Value;
await module.DisposeAsync();
}
}
}
目前您拥有一个可用的对话框。
我添加了以下组件以使其更加方便。
注意:从现在开始,我会使用 Bootstrap 进行样式设计,这很容易更改为 Tailwind。
DialogCloseButton.razor
<button @attributes=CapturedAttributes @onclick=@CloseDialog />
DialogCloseButton.razor.cs
public partial class DialogCloseButton : ComponentBase
{
[CascadingParameter]
public Dialog Dialog { get; set; }
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> CapturedAttributes { get; set; } = new Dictionary<string, object>
{
{ "class", "btn btn-close" }
};
private async Task CloseDialog() => await Dialog.CloseDialogAsync();
}
DialogCloseButton.razor.css
.btn:focus {
box-shadow: none;
}
DialogLayout.razor
<div class="d-flex flex-row justify-content-between border-bottom border-1">
<div class="flex-fill p-1 ps-3 fw-bolder user-select-none app-gradient text-white">
@Header
</div>
<div class="p-1">
<DialogCloseButton />
</div>
</div>
<div class="p-3">
@Content
</div>
DialogLayout.razor.cs
public partial class DialogLayout
{
[Parameter]
public RenderFragment Header { get; set; }
[Parameter]
public RenderFragment Content { get; set; }
}
用法:
<Dialog @ref=@dialog class="p-0 border rounded shadow">
<DialogLayout>
<Header>
<MessagesIcon Size=16 /> Add Message
</Header>
<Content>
<MessageFormView />
</Content>
</DialogLayout>
</Dialog>
<button class="btn btn-outline-success" @onclick=@OpenDialog>Add Message</button>
@code