【问题标题】:auto refresh with blazor server使用 Blazor 服务器自动刷新
【发布时间】:2021-08-31 13:53:49
【问题描述】:

我正在开发 Blazor Server Web 应用程序。 我有一个 SQL Server 数据库和实体框架。

看看这个实体:

public class Room
{
   public int Id {get;set;}
   public String name {get;set;}
   public DateTime closing_date {get;set;}
}

我想在 razor 页面上显示 Room 表格内容:

<Virtualize Items="@rooms" Context="room">
    <table border="1">
    <tr @key=room.Id>
        <td>@room.Id</td>
        <td>@room.Name</td>
        <td>Closing in XXX minutes and YYY seconds</td>
    </tr>
    </table>
</Virtualize>

如您所见,我不想显示结束日期/时间。我想计算关闭前还剩多少分钟。

我可以轻松计算 XXX 和 YYY 值。这很简单。我想做的是每秒刷新一次值。我该怎么做?

在一个经典的 Web 应用程序中,我会使用 setInterval 创建一个 JavaScript 计时器。我如何在 blazor 服务器项目中做到这一点?

谢谢

【问题讨论】:

  • 你可以看看timeago JS库。不止一个。如果可行,那将是最有效的方法。
  • 此库与 Blazor 一起使用?
  • 我不知道...

标签: blazor-server-side


【解决方案1】:

您可以使用System.Timers 命名空间下的Timer 类来完成此操作。

参见示例here

@code {
    private static System.Timers.Timer _timer;
    private int counter = 60;

    protected override void OnInitialized()
    {
        StartTimer();
    }

    public void StartTimer()
    {
        _timer = new System.Timers.Timer(1000);
        _timer.Elapsed += CountDownTimer;
        _timer.Enabled = true;
    }

    public void CountDownTimer(Object source, System.Timers.ElapsedEventArgs e)
    {
        if (counter > 0)
        {
            counter -= 1;
        }
        else
        {
            _timer.Enabled = false;
        }

        StateHasChanged();
    }
}

您可以将其与 Humanizer 之类的内容结合使用,以轻松获得人性化的格式。

您需要创建一个 &lt;tr&gt; 元素的组件,我很方便地使用了 answered elsewhere...

请注意,如果您每秒运行数以千计的此类操作,则需要考虑一些性能问题。无论是降低刷新率还是通过 JavaScript 解决方案继续 Blazor 服务器解决方案。

【讨论】:

  • 根据我的经验,在页面创建事件中创建的计时器有时会失败。 (如 20 中的 1 倍)。我不得不创建一个广播滴答事件的单例服务。
  • 有趣。我从来没有遇到过!我想知道它是否与客户端和服务器之间的延迟有关?
  • 我从来没有发现。我实际上是在使用计时器来等待 SVG 动画完成,然后显示“进入站点”按钮。随机(但平均大约 10% 左右),按钮永远不会显示。用户不喜欢无法进入您的网站,至少有人告诉我! :D 无论如何,在异步页面方法、异步上下文计时器和动画中,Chrome 和/或 Blazor 和/或 VS 调试器决定我太花哨了。
  • 我可以从您的示例中说的一件事是,在 OnInitialized 的两次运行中可能/可能不会产生 2 个计时器。可能会带来令人兴奋的结果!
  • 应该释放计时器并调用 StateHasChanged。 @Bob5421:这真的有效吗?
【解决方案2】:

Henk 在他的评论中是正确的,即您必须处置计时器并调用 StateHasChanged。这是针对 .NET Core 6 进行这些更改的完整解决方案。

剃须刀组件:

@using Microsoft.AspNetCore.Components
@implements IDisposable

<p>Time Remaining:  @_counter</p>

@code
{
    private static System.Timers.Timer _timer;
    private int _counter = 60;

    protected override void OnInitialized()
    {
        _timer = new System.Timers.Timer(1000);
        _timer.Elapsed += CountDownTimer;
        _timer.Enabled = true;
    }

    public async void CountDownTimer(Object source, System.Timers.ElapsedEventArgs e)
    {
        if (_counter > 0)
        {
            _counter -= 1;
        }
        else
        {
            _timer.Enabled = false;
        }

        await InvokeAsync(async () =>
        {
            StateHasChanged();
        });
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

假设组件页面称为“RoomTimer.razor”,则在 Razor 或 MVC 页面上使用它的代码。

 <div class="row">
    <div class="col-md-8">
        <component type="typeof(RoomTimer)" render-mode="ServerPrerendered" />
    </div>
</div>  

@section scripts {
    <script src="_framework/blazor.server.js"></script>
}

【讨论】:

    猜你喜欢
    • 2022-10-19
    • 1970-01-01
    • 2020-10-13
    • 2020-09-13
    • 2020-05-03
    • 1970-01-01
    • 1970-01-01
    • 2022-11-09
    • 1970-01-01
    相关资源
    最近更新 更多