【问题标题】:onSelect function on a select element doesn't get called in Blazor选择元素上的 onSelect 函数不会在 Blazor 中调用
【发布时间】:2021-06-22 08:02:12
【问题描述】:

我目前正在开发一个显示一些电影的应用程序。我有一个 API 可以成功检索电影,还可以选择按特定类型获取电影。为此,我创建了一个 Select 元素,其中动态加载了不同的流派。当点击其中一种流派时,我想通过使用 API 更新电影以仅获取所选流派的电影。

不幸的是,当我选择一个选项时没有任何反应。请注意,我已确认 API 调用有效,因此它必须在此代码中。 这是 HTML 元素:

<div class="content px-sm-3">
    <select>
        <option onselect="async () => await changeMoviesByGenre('None')" value="None">None</option>
        @foreach (var genre in genres)
        {
            <option value=@genre onselect="async () => await changeMoviesByGenre(genre)">@genre</option>
        }
    </select>
</div>

这是应该调用的函数:

private async Task changeMoviesByGenre(string genre) {
        if (genre == "None") {
            movies = await MovieClient.Movies.GetAll();
        }

        else {
            movies = await MovieClient.Movies.GetAllMoviesByGenre(genre);
        }
    }

【问题讨论】:

    标签: html .net api asynchronous blazor


    【解决方案1】:

    OnSelect 不是你想象的那样。当您在 Input 元素中选择文本时会触发它。

    更简单的方法(正如您在回答您的答案时介绍的那样,我已将其作为完整的工作页面包含在答案中)是:

    @page "/Test"
    
    <div class="content px-sm-3 m-2">
        <select @onchange="OnChange">
            <option value="None">None</option>
            @foreach (var genre in genres)
            {
                <option value="@genre">@genre</option>
            }
        </select>
    </div>
    <div class="m-2">Selected: @SelectedGenre</div>
    
    @code {
    
        private List<string> genres
            => new List<string>() { "Rock", "Folk", "Blues", "Pop" };
    
        private string SelectedGenre = string.Empty;
    
        private async Task OnChange(ChangeEventArgs e)
        {
            var selected = e.Value.ToString();
            SelectedGenre = "Getting it, just wait!!!";
            await Task.Delay(3000);
            if (selected.Equals("None", StringComparison.CurrentCultureIgnoreCase))
                this.SelectedGenre = "Give it another Go!";
            else
                this.SelectedGenre = selected;
        }
    }
    

    @Onxxxx(例如@OnChange 和@OnClick)是UI 事件。它们在重新渲染组件之前由 UI 进程运行。 Task 事件处理程序由 UI 运行,并在更新 UI 之前等待 Task。一个 void 事件处理程序由 UI 进程启动,并且如果/何时它产生更新 UI(更复杂和不可预测)。您可以根据需要使用这些代码模式:

    async void MyEventHander() {}` //for handlers that need to do async work and you don't need the UI process to wait on the completion of the handler.
    async Task MyEventHander() {}` //for handlers that need to complete before re-rendering.
    void MyEventHander() {}` //for handlers with no async work.
    
    

    在我的示例中,我添加了await Task.Delay(1000); 来模拟异步数据库调用,因此我可以将处理程序声明为async

    注意:

    1. OnChange 中的 e 是一个对象,因此您可以将其转换为您所期望的。
    2. 初始化时没有选择,所以如果你先选择它,就没有OnChange,因为没有任何改变。

    Ms Docs - Blazor Event Handling

    【讨论】:

    • 我喜欢这个答案。不过,我认为推荐async Task
    • @Bennyboy1973 有趣的一点,我读过有冲突的建议,所以我从EventCallbackFactory 跟踪了 ASPNetCore Repo 中的源代码跟踪。您会看到InvokeAsync 回到EventCallbackWorkItem,它切换到Invoke,返回Task.Completed。如此深入,它看起来就像它下沉一样。如果您正在使用带有等待的组件EventCallback,那么是的,这是一个很好的做法。看起来像马的课程。
    • 不错的侦探。现在让我跟着源代码回到“课程的马”。 :D
    • 感谢您解释为什么这有效而我的初始代码无效!我将 async/await 与 Task 一起使用的原因是,否则 UI 不会更新。我忘记了在哪里找到的,但显然在使用 async void 时不会调用更新 UI 的方法?所以我遇到了我的函数会被调用但列表不会更新的问题,这就是我将 async/await 与 Task 结合使用的原因。
    • @Bram 我已经更新了答案以更贴合您的问题。良好的编码。
    【解决方案2】:

    我设法以某种方式解决了这个问题。 如果您遇到与我相同的问题,我使用 example 修复了它,我不知道它为什么有效,但确实有效。

    我没有使用来自 foreach 的值,而是现在使用 ChangedEventArgs 参数。我还将 onchange 设置为 Select 元素而不是 Options 元素。这就是我的代码现在的样子:

    <div class="content px-sm-3">
        <select @onchange=@changeMovies>
            <option value="None"> None </option>
            @foreach (var genre in genres) {
                <option value=@genre> @genre </option>
            }
        </select>
    </div>
    

    这是被调用的新函数(请注意,这必须是一个任务,否则页面不会更新)

     private async Task changeMovies(ChangeEventArgs e) {
            string selectedGenre = e.Value.ToString();
            if (selectedGenre == "None") {
                movies = await MovieClient.Movies.GetAll();
            }
            else {
                movies = await MovieClient.Movies.GetAllMoviesByGenre(selectedGenre);
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多