【问题标题】:How to set event callback automatically in inherited component?如何在继承的组件中自动设置事件回调?
【发布时间】:2021-05-30 04:46:52
【问题描述】:

目前我有:

<InputText @oninput="@SomeHandler" />

现在我需要使用纯类组件从InputText 继承,并且我想在这个新组件中自动设置事件处理程序,所以我会像这样使用新组件:

<CustomInputText />

如何在自定义组件中设置事件处理程序?

【问题讨论】:

  • 在您的 CustomInputText 中创建一个 EventCallback 类型的参数。此参数可以绑定到 CustomInputText 内的 base.oninput
  • 我该怎么做呢?
  • 您到底期望什么?您想将某些内容传递给组件,还是想从中获取某些内容到使用此自定义组件的剃须刀页面?
  • 我想直接在自定义组件的ctor或OnAfterRender中设置òninput=SomeHandler(或等效项)。
  • 答案似乎是here(并检查其他人)。我将标记重复

标签: blazor blazor-server-side


【解决方案1】:
<InputText @oninput="@SomeHandler" />

@oninput 是一个编译器属性指令,旨在与 Html 标记一起使用,而不是与组件一起使用。 InputText 是一个组件标签,而不是 Html 标签。过去,此类应用程序被忽略或引发编译错误;然而,目前,编译器可能会默默地添加编译器属性指令,但通常可能会导致难以辨别的细微问题。你应该尽量避免这种情况。

如果你想继承 InputText 并像这样使用它:&lt;CustomInputText /&gt;

您只需从InputText 派生,如下所示:

public partial class CustomInputText : InputText
{
   // Add here the internal work...
}

并在 EditForm 上使用(注意:必须嵌入到 EditForm 组件中),像这样:

<EditForm>
   <CustomInputText />
</EditForm>

我想直接在自定义组件的 ctor 或 OnAfterRender 中设置 òninput=SomeHandler(或等效项)

重要的是要了解,虽然组件是 C# 类,但它是类的特例,您不应该尝试将其用作普通 C# 类。例如,你不应该像这样实例化一个组件:

CustomInputText MyCustomInputText = new CustomInputText();

然后调用它的方法和属性,就好像它是一个普通的 C# 类对象一样。您应该像这样将它实例化为组件元素:

<CustomInputText @bind-Value="myValue" /> 

这是因为组件模型的渲染引擎正确地进行了实例化...现在,如果您将组件实例化为就好像它是一个普通的 C# 类对象一样,您将跳过渲染引擎的处理,其中最好的情况会使您的组件无用。我告诉你这个是因为你应该忘记构造函数的 ide。没有构造函数...

Blazor 具有生命周期方法,您应该在初始化组件时覆盖这些方法。

下面是一个代码示例,描述了如何对 InputText 组件进行子类化...复制测试并学习:

NumericInputText.razor.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;


 public partial class NumericInputText : InputText
    {
        protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
        {
            __builder.OpenElement(0, "input");
            __builder.AddAttribute(1, "type", "number");
            __builder.AddMultipleAttributes(2, AdditionalAttributes);
            __builder.AddAttribute(3, "class", CssClass);
            __builder.AddAttribute(4, "value", CurrentValueAsString);
            __builder.AddEventPreventDefaultAttribute(5, "onkeypress", true);
            __builder.AddAttribute(6, "onblur", Microsoft.AspNetCore.Components.EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.FocusEventArgs>(this, OnBlurEventHandler));
            __builder.AddAttribute(7, "onkeydown", Microsoft.AspNetCore.Components.EventCallback.Factory.Create<Microsoft.AspNetCore.Components.Web.KeyboardEventArgs>(this, OnKeyDown));
            __builder.AddAttribute(8, "oninput", Microsoft.AspNetCore.Components.EventCallback.Factory.Create<Microsoft.AspNetCore.Components.ChangeEventArgs>(this, OnInput));
            __builder.CloseElement();
        }

        protected override void OnInitialized()
        {
            CurrentValueAsString = "0";
        }

        private void OnInput(ChangeEventArgs args)
        {
         
            if (args.Value.ToString() == "")
            {
                CurrentValueAsString = "0";
            }
            else
            {
                CurrentValueAsString = args.Value.ToString();

            }
        }

        private void OnKeyDown(KeyboardEventArgs e)
        {
            if (e.Key == "Backspace" && CurrentValueAsString.Length == 1)
            {
                CurrentValueAsString = "";
            }


            if (e.Key == "+")
            {
                var value = int.Parse(CurrentValueAsString);
                value++;
                CurrentValueAsString = value.ToString();
            }
            else if (e.Key == "-")
            {
                var value = int.Parse(CurrentValueAsString);
                value--;
                CurrentValueAsString = value.ToString();
            }


            if (Regex.IsMatch(e.Key, "[0-9]"))
            {
                CurrentValueAsString += int.Parse($"{e.Key}").ToString();

            }

        }

        protected void OnBlurEventHandler(Microsoft.AspNetCore.Components.Web.FocusEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(CurrentValueAsString))
            {
                CurrentValueAsString = "0";
            }

        }

    }  

用法

<EditForm Model="@Model" OnValidSubmit="@HandleValidSubmit" OnInvalidSubmit="@HandleInvalidSubmit">
    <div class="alert @StatusClass">@StatusMessage</div>
    <DataAnnotationsValidator />
    <ValidationSummary />

    <div class="form-group">
        <label for="name">Name: </label>
        <NumericInputText Id="name" Class="form-control" @bind-Value="@Model.NumberSelection" />
        <ValidationMessage For="@(() => Model.NumberSelection)" />
    </div>


    <button type="submit">Ok</button>

</EditForm>

@code {

    private string StatusMessage;
    private string StatusClass;

    private Comment Model = new Comment();

    protected void HandleValidSubmit()
    {
        StatusClass = "alert-info";
        StatusMessage = DateTime.Now + " Handle valid submit";
    }

    protected void HandleInvalidSubmit()
    {
        StatusClass = "alert-danger";
        StatusMessage = DateTime.Now + " Handle invalid submit";
    }


    public class Comment
    {
        public string NumberSelection { get; set; }

    }

}

【讨论】:

  • 我必须在方法开始时添加base.BuildRenderTree(builder);。组件已呈现,但未引发输入事件。如果有其他方法可以使用剃须刀代替,那也可以。
  • "我必须在方法开始时添加 base.BuildRenderTree(builder);" 哪个方法? “组件已呈现,但未引发输入事件”您的意思是当您键入数值时没有任何反应?没办法... 这样做: 1. 运行应用程序 2. 选择零数字并键入 5 3. 现在单击位于文本框右端的向上图标...现在您将看到值6.这意味着之前触发了输入事件,将组件的值设置为5。你也可以调试代码...
猜你喜欢
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 2014-08-31
  • 2021-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多