初始化 Blazor 组件时初始加载数据;页面更新时不要再次触发该查询

Posted

技术标签:

【中文标题】初始化 Blazor 组件时初始加载数据;页面更新时不要再次触发该查询【英文标题】:Load data initially when Blazor component is initialized; don't fire that query again when page is updated 【发布时间】:2021-09-05 06:33:26 【问题描述】:

我有一个 Blazor 组件,它以无序列表的形式显示来自 SQL 的数据。 LoadData 方法由 OnInitialized() 事件调用并填充 List<T>(在本例中为 ProjectModel 列表)。数据量很大,所以我只从 SQL 中获取前 100 行(作为预览)。

我使用 foreach 遍历该列表并为每个元素创建一个 <li>。 这很好用。

但是,该页面还包含一个搜索框。一旦用户输入搜索字符串并单击搜索按钮,就会调用另一种方法再次从 SQL 获取数据,这次是根据用户提供的搜索词进行过滤。过滤是在 SQL 查询中完成的。查询结果再次用于填充 ProjectModels 列表(它会覆盖列表的第一个实例)。

我可以在一毫秒内看到新的过滤列表,然后会弹出初始数据。我猜这是因为再次触发了 OnInitialized,其中包含使用初始数据填充列表的查询。

这是我的组件的样子:

@page "/projects"


<form>
    <input type="search" placeholder="enter search term..." @bind-value="searchTerm">
    <button type="submit" @onclick="GetSearchResults">Search</button>
</form>

<ul>
    @foreach (var project in projects)
    
        <li>@project.ProjectId</li>
        <li>@project.ProjectTitle</li>
        
</ul>

@code 

    private string searchTerm;
    private List<ProjectModel> projects = new List<ProjectModel>();

    protected override void OnInitialized()
    
        projects = GetProjects(); //the method that loads the inital data
    

    private void GetSearchResults()
    
        projects = GetProjectsBySearchTerm(searchTerm);
    



我怎样才能正确地做到这一点?即

    获取页面加载时的初始预览数据并将其放入&lt;ul&gt;&lt;ul&gt;中的数据替换为根据提供的搜索词查询到的数据,同时避免一旦数据发生变化就触发初始加载。

这里是 C# 和 Blazor 新手,所以请放轻松,如果我需要提供更多详细信息,请告诉我。 谢谢大家。

【问题讨论】:

所有答案都为您指明了正确的方向。但是: 1. 你为什么不“分页”你的数据,这样你一次只显示 x 条记录。 2. 使用范围服务来获取和保存您的数据,以便您仅在需要时刷新数据集,而不是每次重新加载视图(页面)时。保存数据的服务未链接到您的页面/视图。如果你有兴趣,我会给你一些资源。 @MrCakaShaunCurtis 是的,有关范围服务的一些信息会很有帮助。谢谢。 【参考方案1】:

这是因为form - 您的button 正在提交表单,这会导致浏览器重新加载页面。

最简单的解决方法 - 不要在 SPA 应用上使用表单,除非您真的想重新加载页面。

【讨论】:

【参考方案2】:

Blazor 和普通html。提交按钮重新加载页面。当页面重新加载时,它会启动 OnInitialize 函数。在 blazor 中最好使用普通按钮。在您的代码中,只需从按钮中删除 type="submit"。这将使它工作。此外,您不需要将其放入表单中,因为您不会将整个表单发送到后端。

将您的代码更改为:

<div>
    <input type="search" placeholder="enter search term..." @bind-value="searchTerm">
    <button  @onclick="GetSearchResults">Search</button>
</div>

【讨论】:

【参考方案3】:

我很确定您可以只使用@bind 而不是@bind-value。但是,问题在于表单/提交。没有理由提交任何内容,因为您不会从该页面发送数据。此外,如果PreRender 处于打开状态(默认情况下),OnInitialized 会触发 2 次。如果这真的让您感到困扰,请将您的数据加载到OnAfterRender 并检查firstRender

【讨论】:

以上是关于初始化 Blazor 组件时初始加载数据;页面更新时不要再次触发该查询的主要内容,如果未能解决你的问题,请参考以下文章

根据页面的顶部和左侧位置在页面上显示 Blazor 组件

如何同时从不同的 Blazor 组件进行数据调用?

如何在使用 observable 更新数组时更新 *ngFor 以及如何在网站加载时初始化 observable?

Vue 刷新页面时会触发事件吗

如何检测到所有页面组件都已加载到 Oro 应用程序中?

Blazor:如何存储页面状态(所有组件状态)?