我有一个类似聊天的 Blazor 应用程序,我需要不断向其中添加 DOM 元素:
<EditForm model="this" OnValidSubmit="@Query">
<div id="qrContainer">
<div>
<input type="text" @ref="queryElement" @bind="query" />
</div>
<div>
<div id="output" @bind="response"></div>
</div>
</div>
</EditForm>
@code {
private String query { get; set; } = null;
private String response { get; set; }
private ElementReference queryElement;
private async Task Query(){
// ...
var responseString = await responseService.getResponseAsync(query);
// Need to add DOM element to "output" here.
// ...
}
}
据我了解,JSInterop 不是执行此操作的首选方法。那么,如何以“Blazor”方式添加新的 DOM 元素?
我认为你的思考方向是错误的。 您会发现需要将新的
responseString
添加到 DOM 中。 您实际需要做的是让组件[在本例中为页面]根据数据状态处理 DOM 更新。
这是一个基于您的代码片段的非常简单的示例。
记录、保存数据的单例服务以及通知注册处理程序发生更改的事件。
public record Comment(DateTime TimeStamp, string Value);
public class ChatRoom
{
public event EventHandler? ItemsChanged;
private readonly List<Comment> _items = new();
public IEnumerable<Comment> Items => _items.OrderByDescending(item => item.TimeStamp);
public void PostComment(string comment)
{
_items.Add(new(DateTime.Now, comment));
this.ItemsChanged?.Invoke(null, EventArgs.Empty);
}
}
还有聊天页面 [在本例中为
Home
]。
@page "/"
@inject ChatRoom ChatRoom
@implements IDisposable
<PageTitle>Home</PageTitle>
<h1>Chat world!</h1>
<textarea class="form-control" @bind=_currentComment @bind:event="oninput" />
<div class="text-end m-2">
<button class="btn btn-primary btn-sm" disabled="@_noComment" @onclick="AddComment">Add Comment</button>
</div>
@foreach (var item in ChatRoom.Items)
{
<div class="bg-light m-2 p-2 border border-1 rounded-3">@item.Value</div>
}
@code {
private string? _currentComment;
private bool _noComment => string.IsNullOrWhiteSpace(_currentComment);
protected override void OnInitialized()
=> this.ChatRoom.ItemsChanged += this.OnItemsChanged;
private void AddComment()
{
if (_currentComment is not null)
ChatRoom.PostComment(_currentComment);
_currentComment = null;
}
public void OnItemsChanged(object? sender, EventArgs e)
=> this.InvokeAsync(this.StateHasChanged);
public void Dispose()
=> this.ChatRoom.ItemsChanged -= this.OnItemsChanged;
}
两个浏览器窗口交互: