BlazorASP.NET Core datová vazba
Razor Komponenty poskytují funkce datových vazeb s @bind Razor atributem direktivy s polem, vlastností nebo hodnotou Razor výrazu.
Následující příklad vytvoří vazbu:
- Hodnota
<input>prvku pole jazykainputValueC#. - Druhá hodnota
<input>prvku vlastnosti jazykaInputValueC#.
Když prvek <input> ztratí fokus, aktualizuje se jeho vázané pole nebo vlastnost.
Pages/Bind.razor:
@page "/bind"
<p>
<input @bind="inputValue" />
</p>
<p>
<input @bind="InputValue" />
</p>
<ul>
<li><code>inputValue</code>: @inputValue</li>
<li><code>InputValue</code>: @InputValue</li>
</ul>
@code {
private string? inputValue;
private string? InputValue { get; set; }
}
Textové pole se v uživatelském rozhraní aktualizuje jenom při vykreslení komponenty, nikoli v reakci na změnu hodnoty pole nebo vlastnosti. Vzhledem k tomu, že se komponenty vykreslují po spuštění kódu obslužné rutiny události, změny polí a vlastností se obvykle projeví v uživatelském rozhraní ihned po aktivaci obslužné rutiny události.
Jako ukázku toho, jak se datová vazba sčítá v HTML, následující příklad naváže vlastnost na atributy InputValue a <input> druhého value onchange prvku. Druhým prvkem v následujícím příkladu je ukázka konceptu, která nemá navrhovat způsob vazby <input> dat v Razor komponentách.
Pages/BindTheory.razor:
@page "/bind-theory"
<p>
<label>
Normal Blazor binding:
<input @bind="InputValue" />
</label>
</p>
<p>
<label>
Demonstration of equivalent HTML binding:
<input value="@InputValue"
@onchange="@((ChangeEventArgs __e) => InputValue = __e?.Value?.ToString())" />
</label>
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string? InputValue { get; set; }
}
Při vykreslení komponenty pochází element ukázky BindTheory HTML z vlastnosti value <input> InputValue . Když uživatel zadá hodnotu do textového pole a změní fokus prvku, událost se aktivuje a vlastnost se nastaví onchange InputValue na změněnou hodnotu. Ve skutečnosti je spouštění kódu složitější, protože @bind zpracovává případy, kdy se provádí převody typů. Obecně platí, že aktuální hodnotu výrazu přidruží k atributu a zpracovává @bind změny pomocí registrované obslužné value rutiny.
Vytvořte vazbu vlastnosti nebo pole u jiných model DOM (Document Object Model) (DOM) zahrnutím atributu s @bind:event="{EVENT}" událostí modelu DOM pro zástupný {EVENT} symbol. Následující příklad vytvoří vazbu vlastnosti na hodnotu prvku InputValue <input> při aktivaci oninput události prvku. Na rozdíl onchange od události, která se vyžádá, když prvek ztratí fokus, se při změně hodnoty oninput textového pole vyhodí.
Page/BindEvent.razor:
@page "/bind-event"
<p>
<input @bind="InputValue" @bind:event="oninput" />
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string? InputValue { get; set; }
}
Razor V vazbě atributů se rozlišují velká a malá písmena:
@bind``@bind:eventa jsou platné.@Bind/@Bind:Event(velká písmenaBEa ) nebo@BIND/@BIND:EVENT(všechna velká písmena) jsou neplatná.
Výběr více možností <input> s prvky
Vazba podporuje multiple výběr možností s <input> elementy. Událost @onchange poskytuje pole vybraných prvků prostřednictvím argumentů událostí ( ChangeEventArgs ). Hodnota musí být svázaná s typem pole.
Pages/BindMultipleInput.razor:
@page "/bind-multiple-input"
<h1>Bind Multiple <code>input</code>Example</h1>
<p>
<label>
Select one or more cars:
<select @onchange="SelectedCarsChanged" multiple>
<option value="audi">Audi</option>
<option value="jeep">Jeep</option>
<option value="opel">Opel</option>
<option value="saab">Saab</option>
<option value="volvo">Volvo</option>
</select>
</label>
</p>
<p>
Selected Cars: @string.Join(", ", SelectedCars)
</p>
<p>
<label>
Select one or more cities:
<select @bind="SelectedCities" multiple>
<option value="bal">Baltimore</option>
<option value="la">Los Angeles</option>
<option value="pdx">Portland</option>
<option value="sf">San Francisco</option>
<option value="sea">Seattle</option>
</select>
</label>
</p>
<span>
Selected Cities: @string.Join(", ", SelectedCities)
</span>
@code {
public string[] SelectedCars { get; set; } = new string[] { };
public string[] SelectedCities { get; set; } = new[] { "bal", "sea" };
void SelectedCarsChanged(ChangeEventArgs e)
{
SelectedCars = (string[])e.Value;
}
}
Informace o tom, jak se zpracovávají prázdné řetězce a hodnoty v datové vazbě, najdete v části Možnosti elementu Vazby na null hodnoty objektů <select> null jazyka C#.
Možnosti <select> elementu vazby na hodnoty objektů jazyka null C#
Neexistuje žádný rozumný způsob, jak reprezentovat hodnotu možnosti prvku jako hodnotu objektu <select> jazyka null C#, protože:
- Atributy HTML nemůže mít
nullhodnoty. Nejbližší ekvivalent vnullHTML je absence atributu HTML vvalue<option>elementu . - Při výběru objektu bez atributu prohlížeč považuje hodnotu za
<option>valuetextový obsah tohoto<option>elementu .
Rozhraní Blazor se nepokusí potlačit výchozí chování, protože by zahrnovalo:
- Vytvoření řetězce alternativních řešení pro zvláštní případy v rámci architektury
- Rozbíjení změn chování aktuální architektury
Nejužitelnějším null ekvivalentem v HTML je prázdný řetězec value . Rozhraní Blazor zpracovává null převody prázdných řetězců pro dvousestavovou vazbu <select> na hodnotu typu .
Nepochyitelné hodnoty
Když uživatel poskytne neopravitelnou hodnotu prvku vázaného na data, neopravitelná hodnota se při aktivaci události vazby automaticky vrátí na předchozí hodnotu.
Vezměte v úvahu následující komponentu, kde je prvek svázán s <input> int typem s počáteční hodnotou 123 .
Pages/UnparsableValues.razor:
@page "/unparseable-values"
<p>
<input @bind="inputValue" />
</p>
<p>
<code>inputValue</code>: @inputValue
</p>
@code {
private int inputValue = 123;
}
Vazba se ve výchozím nastavení vztahuje na událost onchange elementu. Pokud uživatel aktualizuje hodnotu položky textového pole na a změní fokus, hodnota prvku se při spuštění 123.45 123 vrátí na onchange . Když se hodnota zamítne ve prospěch původní hodnoty , uživatel pochopí, že jeho 123.45 123 hodnota nebyla přijata.
V případě události ( ) dojde k převrácení hodnoty po stisknutí klávesy, která zavádí oninput @bind:event="oninput" neopravitelnou hodnotu. Při cílení na událost s typem svázaným s objektem je uživateli znemožněn zadávání oninput int tečky ( . ). Tečka ( ) je okamžitě odebrána, takže uživatel obdrží okamžitou zpětnou vazbu, že . jsou povolena pouze celá čísla. Existují scénáře, kdy vrácení hodnoty události není ideální, například kdy by uživatel měl mít povoleno vymazat neopravitelnou oninput <input> hodnotu. Mezi alternativy patří:
- Nepoužívejte
oninputudálost . Použijte výchozí událost, kde se neplatná hodnota nevrátila,onchangedokud prvek neztratí fokus. - Vytvořte vazbu na typ s možnou hodnotou null, například nebo , a zadejte vlastní logiku a logiku přístupového objektu pro
int?stringzpracování neplatnýchgetsetpoložek. - Použijte komponentu ověřování formuláře, například InputNumber<TValue> nebo InputDate<TValue> . Součásti ověřování formulářů poskytují integrovanou podporu pro správu neplatných vstupů. Součásti ověřování formulářů:
- Povolte uživateli zadání neplatného vstupu a příjem chyb ověření v přidruženém souboru EditContext .
- Zobrazení chyb ověřování v uživatelském rozhraní bez toho, aby uživatel zasahoval do zadávání dalších dat webového formuláře
Formátování řetězců
Datová vazba funguje s jedním DateTime formátovacím řetězcem pomocí @bind:format="{FORMAT STRING}" , kde zástupný symbol je {FORMAT STRING} formátovací řetězec. Jiné výrazy formátu, jako jsou formáty měn nebo čísel, nejsou v tuto chvíli dostupné, ale můžou být přidány v budoucí verzi.
Pages/DateBinding.razor:
@page "/date-binding"
<p>
<label>
<code>yyyy-MM-dd</code> format:
<input @bind="startDate" @bind:format="yyyy-MM-dd" />
</label>
</p>
<p>
<code>startDate</code>: @startDate
</p>
@code {
private DateTime startDate = new(2020, 1, 1);
}
V předchozím kódu má typ pole elementu <input> type (atribut) výchozí hodnotu text .
S System.DateTime povolenou hodnotou null System.DateTimeOffset a jsou podporovány:
private DateTime? date;
private DateTimeOffset? dateOffset;
Zadání formátu pro typ pole se nedoporučuje, protože má integrovanou podporu date Blazor formátování kalendářních dat. I přes doporučení používejte formát data pro vazbu, aby správně fungovala, pouze pokud je dodaný formát yyyy-MM-dd s date typem pole:
<input type="date" @bind="startDate" @bind:format="yyyy-MM-dd">
Vlastní formáty vazeb
Jazyk C# a get set přístupové objekty lze použít k vytvoření vlastního chování formátu vazby, jak ukazuje následující DecimalBinding komponenta. Komponenta vytvoří vazbu kladného nebo záporného desetinného čísla až se třemi desetinnými místy na <input> prvek pomocí vlastnosti ( string DecimalValue ).
Pages/DecimalBinding.razor:
@page "/decimal-binding"
@using System.Globalization
<p>
<label>
Decimal value (±0.000 format):
<input @bind="DecimalValue" />
</label>
</p>
<p>
<code>decimalValue</code>: @decimalValue
</p>
@code {
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
{
get => decimalValue.ToString("0.000", culture);
set
{
if (Decimal.TryParse(value, style, culture, out var number))
{
decimalValue = Math.Round(number, 3);
}
}
}
}
Vytvoření vazby s parametry komponenty
Běžným scénářem je vazba vlastnosti podřízené komponenty na vlastnost v její nadřazené komponentě. Tento scénář se nazývá zřetězovaná vazba, protože současně dochází k více úrovním vazby.
Parametry komponenty povolují vlastnosti vazby nadřazené komponenty se @bind-{PROPERTY} syntaxí, kde zástupný symbol je {PROPERTY} vlastnost, která se má svázat.
V podřízené komponentě nelze implementovat zřetězované vazby @bind se syntaxí. Obslužná rutina události a hodnota musí být zadány samostatně pro podporu aktualizace vlastnosti v nadřazené z podřízené komponenty.
Nadřazená komponenta stále využívá syntaxi k nastavení datové @bind vazby s podřízeným komponentou.
Následující ChildBind komponenta má parametr komponenty a Year EventCallback<TValue> . Podle konvence musí být parametr pro pojmenován jako název parametru komponenty EventCallback<TValue> s Changed příponou " ". Syntaxe pojmenování je {PARAMETER NAME}Changed , kde zástupný symbol je název {PARAMETER NAME} parametru. V následujícím příkladu má EventCallback<TValue> název YearChanged .
EventCallback.InvokeAsync vyvolá delegáta přidruženého k vazbě se poskytnutým argumentem a odešle oznámení události pro změněnou vlastnost.
Shared/ChildBind.razor:
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
</p>
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
</div>
</div>
@code {
private Random r = new();
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild()
{
await YearChanged.InvokeAsync(r.Next(1950, 2021));
}
}
Další informace o událostech EventCallback<TValue> a najdete v části EventCallback tohoto ASP.NET Core Blazor zpracování událostí článku.
V následující Parent komponentě year je pole vázané na parametr podřízené Year komponenty. Parametr Year je možné svázat, protože má doprovodnou YearChanged událost, která odpovídá typu Year parametru.
Pages/Parent.razor:
@page "/Parent"
<h1>Parent Component</h1>
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private Random r = new();
private int year = 1979;
private void UpdateYear()
{
year = r.Next(1950, 2021);
}
}
Podle konvence může být vlastnost svázaná s odpovídající obslužnou rutinou události zahrnutím atributu přiřazeného obslužné rutině, kde zástupný symbol @bind-{PROPERTY}:event {PROPERTY} je vlastnost . <ChildBind @bind-Year="year" /> je ekvivalentem zápisu:
<ChildBind @bind-Year="year" @bind-Year:event="YearChanged" />
V sofistikovanějším příkladu z reálného světa se používá následující PasswordEntry komponenta:
- Nastaví
<input>hodnotu prvku napasswordpole. - Zpřístupňuje změny vlastnosti nadřazené komponentě pomocí objektu , který předává aktuální hodnotu podřízeného pole
PasswordEventCallbackjako svůjpasswordargument. - Použije
onclickudálost k aktivaciToggleShowPasswordmetody . Další informace naleznete v tématu ASP.NET Core Blazor zpracování událostí.
Shared/PasswordEntry.razor:
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
</p>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
</div>
</div>
@code {
private bool showPassword;
private string? password;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
{
password = e?.Value?.ToString();
await PasswordChanged.InvokeAsync(password);
}
private void ToggleShowPassword()
{
showPassword = !showPassword;
}
}
Komponenta PasswordEntry se používá v jiné komponentě, například v následujícím PasswordBinding příkladu komponenty.
Pages/PasswordBinding.razor:
@page "/password-binding"
<h1>Password Binding</h1>
<PasswordEntry @bind-Password="password" />
<p>
<code>password</code>: @password
</p>
@code {
private string password = "Not set";
}
Při PasswordBinding počátečním vykreslení komponenty se v uživatelském rozhraní password zobrazí hodnota Not set . Po počátečním vykreslení hodnota odráží změny provedené v hodnotě parametru komponenty password Password v PasswordEntry komponentě.
Poznámka
Předchozí příklad vytvoří vazbu hesla jedním směrem z podřízené komponenty na PasswordEntry nadřazenou PasswordBinding komponentu. Dvousměnná vazba není v tomto scénáři požadavkem, pokud je cílem aplikace mít sdílenou komponentu pro zadávání hesel, aby ji bylo možné opakovaně používat v aplikaci, která pouze předává heslo nadřazenému serveru. Přístup, který umožňuje dvoucestné vazby bez přímého zápisu do parametru podřízené komponenty ,najdete v příkladu komponenty v části Vázání napříč více než dvěma součástmi NestedChild tohoto článku.
Provádění kontrol nebo zahodování chyb v obslužné rutině Následující revidovaná komponenta poskytuje uživateli okamžitou zpětnou vazbu, pokud se v hodnotě PasswordEntry hesla používá mezera.
Shared/PasswordEntry.razor:
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
</p>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
</div>
</div>
@code {
private bool showPassword;
private string? password;
private string? validationMessage;
[Parameter]
public string? Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
{
password = e?.Value?.ToString();
if (password != null && password.Contains(' '))
{
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
}
else
{
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
}
}
private void ToggleShowPassword()
{
showPassword = !showPassword;
}
}
Vytvoření vazby mezi více než dvěma komponentami
Parametry můžete svázat s libovolným počtem vnořených komponent, ale musíte respektovat jednosměnné toky dat:
- Oznámení o změně se chytou nahoru v hierarchii.
- Nové hodnoty parametrů prochádí hierarchii .
Běžným a doporučeným přístupem je ukládat pouze podkladová data v nadřazené komponentě, aby nedocházelo k nejasnostem o tom, jaký stav je třeba aktualizovat, jak je znázorněno v následujícím příkladu.
Pages/Parent.razor:
@page "/parent"
<h1>Parent Component</h1>
<p>Parent Message: <b>@parentMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Parent</button>
</p>
<NestedChild @bind-ChildMessage="parentMessage" />
@code {
private string parentMessage = "Initial value set in Parent";
private void ChangeValue()
{
parentMessage = $"Set in Parent {DateTime.Now}";
}
}
Shared/NestedChild.razor:
<div class="border rounded m-1 p-1">
<h2>Child Component</h2>
<p>Child Message: <b>@ChildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Child</button>
</p>
<NestedGrandchild @bind-GrandchildMessage="BoundValue" />
</div>
@code {
[Parameter]
public string? ChildMessage { get; set; }
[Parameter]
public EventCallback<string> ChildMessageChanged { get; set; }
private string BoundValue
{
get => ChildMessage ?? string.Empty;
set => ChildMessageChanged.InvokeAsync(value);
}
private async Task ChangeValue()
{
await ChildMessageChanged.InvokeAsync(
$"Set in Child {DateTime.Now}");
}
}
Upozornění
Obecně se vyhněte vytváření komponent, které zapisují přímo do vlastních parametrů součásti. Předchozí komponenta místo přímého zápisu do svého parametru používá NestedChild BoundValue vlastnost ChildMessage . Další informace naleznete v tématu RazorASP.NET Core Součásti.
Shared/NestedGrandchild.razor:
<div class="border rounded m-1 p-1">
<h3>Grandchild Component</h3>
<p>Grandchild Message: <b>@GrandchildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Grandchild</button>
</p>
</div>
@code {
[Parameter]
public string? GrandchildMessage { get; set; }
[Parameter]
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue()
{
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
}
}
Alternativní přístup vhodný ke sdílení dat v paměti a mezi komponentami, které nejsou nutně vnořené, najdete v tématu ASP.NET Core Blazor Správa stavu .
Další zdroje informací
Razor Komponenty poskytují funkce datových vazeb s @bind Razor atributem direktivy s polem, vlastností nebo hodnotou Razor výrazu.
Následující příklad vytvoří vazbu:
- Hodnota
<input>prvku pole jazykainputValueC#. - Druhá hodnota
<input>prvku vlastnosti jazykaInputValueC#.
Když prvek <input> ztratí fokus, aktualizuje se jeho vázané pole nebo vlastnost.
Pages/Bind.razor:
@page "/bind"
<p>
<input @bind="inputValue" />
</p>
<p>
<input @bind="InputValue" />
</p>
<ul>
<li><code>inputValue</code>: @inputValue</li>
<li><code>InputValue</code>: @InputValue</li>
</ul>
@code {
private string inputValue;
private string InputValue { get; set; }
}
Textové pole se v uživatelském rozhraní aktualizuje jenom při vykreslení komponenty, nikoli v reakci na změnu hodnoty pole nebo vlastnosti. Vzhledem k tomu, že se komponenty vykreslují po spuštění kódu obslužné rutiny události, změny polí a vlastností se obvykle projeví v uživatelském rozhraní ihned po aktivaci obslužné rutiny události.
Jako ukázku toho, jak se datová vazba sčítá v HTML, následující příklad naváže vlastnost na atributy InputValue a <input> druhého value onchange prvku. Druhým prvkem v následujícím příkladu je ukázka konceptu, která nemá navrhovat způsob vazby <input> dat v Razor komponentách.
Pages/BindTheory.razor:
@page "/bind-theory"
<p>
<label>
Normal Blazor binding:
<input @bind="InputValue" />
</label>
</p>
<p>
<label>
Demonstration of equivalent HTML binding:
<input value="@InputValue"
@onchange="@((ChangeEventArgs __e) => InputValue = __e.Value.ToString())" />
</label>
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string InputValue { get; set; }
}
Při vykreslení komponenty pochází element ukázky BindTheory HTML z vlastnosti value <input> InputValue . Když uživatel zadá hodnotu do textového pole a změní fokus prvku, událost se aktivuje a vlastnost se nastaví onchange InputValue na změněnou hodnotu. Ve skutečnosti je spouštění kódu složitější, protože @bind zpracovává případy, kdy se provádí převody typů. Obecně platí, že aktuální hodnotu výrazu přidruží k atributu a zpracovává @bind změny pomocí registrované obslužné value rutiny.
Vytvořte vazbu vlastnosti nebo pole u jiných model DOM (Document Object Model) (DOM) zahrnutím atributu s @bind:event="{EVENT}" událostí modelu DOM pro zástupný {EVENT} symbol. Následující příklad vytvoří vazbu vlastnosti na hodnotu prvku InputValue <input> při aktivaci oninput události prvku. Na rozdíl onchange od události, která se vyžádá, když prvek ztratí fokus, se při změně hodnoty oninput textového pole vyhodí.
Page/BindEvent.razor:
@page "/bind-event"
<p>
<input @bind="InputValue" @bind:event="oninput" />
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string InputValue { get; set; }
}
Razor V vazbě atributů se rozlišují velká a malá písmena:
@bind``@bind:eventa jsou platné.@Bind/@Bind:Event(velká písmenaBEa ) nebo@BIND/@BIND:EVENT(všechna velká písmena) jsou neplatná.
Možnosti <select> elementu vazby na hodnoty objektů jazyka null C#
Neexistuje žádný rozumný způsob, jak reprezentovat hodnotu možnosti prvku jako hodnotu objektu <select> jazyka null C#, protože:
- Atributy HTML nemůže mít
nullhodnoty. Nejbližší ekvivalent vnullHTML je absence atributu HTML vvalue<option>elementu . - Při výběru objektu bez atributu prohlížeč považuje hodnotu za
<option>valuetextový obsah tohoto<option>elementu .
Rozhraní Blazor se nepokusí potlačit výchozí chování, protože by zahrnovalo:
- Vytvoření řetězce alternativních řešení pro zvláštní případy v rámci architektury
- Rozbíjení změn chování aktuální architektury
Nejužitelnějším null ekvivalentem v HTML je prázdný řetězec value . Rozhraní Blazor zpracovává null převody prázdných řetězců pro dvousestavovou vazbu <select> na hodnotu typu .
Nepochyitelné hodnoty
Když uživatel poskytne neopravitelnou hodnotu prvku vázaného na data, neopravitelná hodnota se při aktivaci události vazby automaticky vrátí na předchozí hodnotu.
Vezměte v úvahu následující komponentu, kde je prvek svázán s <input> int typem s počáteční hodnotou 123 .
Pages/UnparsableValues.razor:
@page "/unparseable-values"
<p>
<input @bind="inputValue" />
</p>
<p>
<code>inputValue</code>: @inputValue
</p>
@code {
private int inputValue = 123;
}
Vazba se ve výchozím nastavení vztahuje na událost onchange elementu. Pokud uživatel aktualizuje hodnotu položky textového pole na a změní fokus, hodnota prvku se při spuštění 123.45 123 vrátí na onchange . Když se hodnota zamítne ve prospěch původní hodnoty , uživatel pochopí, že jeho 123.45 123 hodnota nebyla přijata.
V případě události ( ) dojde k převrácení hodnoty po stisknutí klávesy, která zavádí oninput @bind:event="oninput" neopravitelnou hodnotu. Při cílení na událost s typem svázaným s objektem je uživateli znemožněn zadávání oninput int tečky ( . ). Tečka ( ) je okamžitě odebrána, takže uživatel obdrží okamžitou zpětnou vazbu, že . jsou povolena pouze celá čísla. Existují scénáře, kdy vrácení hodnoty události není ideální, například kdy by uživatel měl mít povoleno vymazat neopravitelnou oninput <input> hodnotu. Mezi alternativy patří:
- Nepoužívejte
oninputudálost . Použijte výchozí událost, kde se neplatná hodnota nevrátila,onchangedokud prvek neztratí fokus. - Vytvořte vazbu na typ s možnou hodnotou null, například nebo , a zadejte vlastní logiku a přístupový objekt pro
int?stringzpracování neplatnýchgetsetpoložek. - Použijte komponentu ověřování formuláře, například InputNumber<TValue> nebo InputDate<TValue> . Součásti ověřování formulářů poskytují integrovanou podporu pro správu neplatných vstupů. Součásti ověřování formulářů:
- Povolte uživateli zadání neplatného vstupu a příjem chyb ověření v přidruženém souboru EditContext .
- Zobrazovat chyby ověřování v uživatelském rozhraní bez toho, aby uživatel zasahoval do zadávání dalších dat webového formuláře.
Formátování řetězců
Datová vazba funguje s jedním DateTime formátovacím řetězcem pomocí @bind:format="{FORMAT STRING}" , kde zástupný symbol je {FORMAT STRING} formátovací řetězec. Jiné výrazy formátu, jako jsou formáty měn nebo čísel, nejsou v tuto chvíli dostupné, ale můžou být přidány v budoucí verzi.
Pages/DateBinding.razor:
@page "/date-binding"
<p>
<label>
<code>yyyy-MM-dd</code> format:
<input @bind="startDate" @bind:format="yyyy-MM-dd" />
</label>
</p>
<p>
<code>startDate</code>: @startDate
</p>
@code {
private DateTime startDate = new(2020, 1, 1);
}
V předchozím kódu je typ pole elementu <input> ( type atribut) ve výchozím nastavení text .
S System.DateTime povolenou hodnotou null System.DateTimeOffset a jsou podporovány:
private DateTime? date;
private DateTimeOffset? dateOffset;
Zadání formátu pro typ pole se nedoporučuje, protože má integrovanou podporu date Blazor formátování kalendářních dat. I přes doporučení používejte formát data pro vazbu, aby správně fungovala, pouze pokud je dodaný formát yyyy-MM-dd s date typem pole:
<input type="date" @bind="startDate" @bind:format="yyyy-MM-dd">
Vlastní formáty vazeb
Jazyk C# a get set přístupové objekty lze použít k vytvoření vlastního chování formátu vazby, jak ukazuje následující DecimalBinding komponenta. Komponenta vytvoří vazbu kladného nebo záporného desetinného čísla až se třemi desetinnými místy na <input> prvek pomocí vlastnosti ( string DecimalValue ).
Pages/DecimalBinding.razor:
@page "/decimal-binding"
@using System.Globalization
<p>
<label>
Decimal value (±0.000 format):
<input @bind="DecimalValue" />
</label>
</p>
<p>
<code>decimalValue</code>: @decimalValue
</p>
@code {
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
{
get => decimalValue.ToString("0.000", culture);
set
{
if (Decimal.TryParse(value, style, culture, out var number))
{
decimalValue = Math.Round(number, 3);
}
}
}
}
Vazba s parametry komponenty
Běžným scénářem je vazba vlastnosti podřízené komponenty na vlastnost v její nadřazené komponentě. Tento scénář se nazývá zřetězovaná vazba, protože současně dochází k více úrovním vazby.
Parametry komponenty povolují vlastnosti vazby nadřazené komponenty se @bind-{PROPERTY} syntaxí, kde zástupný symbol je {PROPERTY} vlastnost, která se má svázat.
V podřízené komponentě nelze implementovat zřetězované vazby @bind se syntaxí. Obslužná rutina události a hodnota musí být zadány samostatně pro podporu aktualizace vlastnosti v nadřazené z podřízené komponenty.
Nadřazená komponenta stále využívá syntaxi k nastavení datové @bind vazby s podřízeným komponentou.
Následující ChildBind komponenta má parametr komponenty a Year EventCallback<TValue> . Podle konvence musí být parametr pro pojmenován jako název parametru komponenty EventCallback<TValue> s Changed příponou " ". Syntaxe pojmenování je {PARAMETER NAME}Changed , kde zástupný symbol je název {PARAMETER NAME} parametru. V následujícím příkladu má EventCallback<TValue> název YearChanged .
EventCallback.InvokeAsync vyvolá delegáta přidruženého k vazbě se poskytnutým argumentem a odešle oznámení události pro změněnou vlastnost.
Shared/ChildBind.razor:
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
</p>
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
</div>
</div>
@code {
private Random r = new();
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild()
{
await YearChanged.InvokeAsync(r.Next(1950, 2021));
}
}
Další informace o událostech EventCallback<TValue> a najdete v části EventCallback tohoto ASP.NET Core Blazor zpracování událostí článku.
V následující Parent komponentě year je pole vázané na parametr podřízené Year komponenty. Parametr Year je možné svázat, protože má doprovodnou YearChanged událost, která odpovídá typu Year parametru.
Pages/Parent.razor:
@page "/Parent"
<h1>Parent Component</h1>
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private Random r = new();
private int year = 1979;
private void UpdateYear()
{
year = r.Next(1950, 2021);
}
}
Podle konvence může být vlastnost svázaná s odpovídající obslužnou rutinou události zahrnutím atributu přiřazeného obslužné rutině, kde zástupný symbol @bind-{PROPERTY}:event {PROPERTY} je vlastnost . <ChildBind @bind-Year="year" /> je ekvivalentem zápisu:
<ChildBind @bind-Year="year" @bind-Year:event="YearChanged" />
V sofistikovanějším příkladu z reálného světa se používá následující PasswordEntry komponenta:
- Nastaví
<input>hodnotu prvku napasswordpole. - Zpřístupňuje změny vlastnosti nadřazené komponentě pomocí objektu , který předává aktuální hodnotu podřízeného pole
PasswordEventCallbackjako svůjpasswordargument. - Použije
onclickudálost k aktivaciToggleShowPasswordmetody . Další informace naleznete v tématu ASP.NET Core Blazor zpracování událostí.
Shared/PasswordEntry.razor:
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
</p>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
</div>
</div>
@code {
private bool showPassword;
private string password;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
{
password = e.Value.ToString();
await PasswordChanged.InvokeAsync(password);
}
private void ToggleShowPassword()
{
showPassword = !showPassword;
}
}
Komponenta PasswordEntry se používá v jiné komponentě, například v následujícím PasswordBinding příkladu komponenty.
Pages/PasswordBinding.razor:
@page "/password-binding"
<h1>Password Binding</h1>
<PasswordEntry @bind-Password="password" />
<p>
<code>password</code>: @password
</p>
@code {
private string password = "Not set";
}
Při PasswordBinding počátečním vykreslení komponenty se v uživatelském rozhraní password zobrazí hodnota Not set . Po počátečním vykreslení hodnota odráží změny provedené v hodnotě parametru komponenty password Password v PasswordEntry komponentě.
Poznámka
Předchozí příklad vytvoří vazbu hesla jedním směrem z podřízené komponenty na PasswordEntry nadřazenou PasswordBinding komponentu. Dvousměnná vazba není v tomto scénáři požadavkem, pokud je cílem aplikace mít sdílenou komponentu pro zadávání hesel, aby ji bylo možné opakovaně používat v aplikaci, která jenom předává heslo nadřazenému serveru. Přístup, který umožňuje dvoucestné vazby bez přímého zápisu do parametru podřízené komponenty ,najdete v příkladu komponenty v části Vázání napříč více než dvěma součástmi NestedChild tohoto článku.
Provádění kontrol nebo zachytání chyb v obslužné rutině Následující revidovaná komponenta poskytuje uživateli okamžitou zpětnou vazbu, pokud se v hodnotě PasswordEntry hesla používá mezera.
Shared/PasswordEntry.razor:
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
</p>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
</div>
</div>
@code {
private bool showPassword;
private string password;
private string validationMessage;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
{
password = e.Value.ToString();
if (password.Contains(' '))
{
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
}
else
{
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
}
}
private void ToggleShowPassword()
{
showPassword = !showPassword;
}
}
Vytvoření vazby mezi více než dvěma komponentami
Parametry můžete svázat s libovolným počtem vnořených komponent, ale musíte respektovat jednosměnné toky dat:
- Oznámení o změně se chytou nahoru v hierarchii.
- Nové hodnoty parametrů prochádí hierarchii .
Běžným a doporučeným přístupem je ukládat pouze podkladová data v nadřazené komponentě, aby nedocházelo k nejasnostem o tom, jaký stav je třeba aktualizovat, jak je znázorněno v následujícím příkladu.
Pages/Parent.razor:
@page "/parent"
<h1>Parent Component</h1>
<p>Parent Message: <b>@parentMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Parent</button>
</p>
<NestedChild @bind-ChildMessage="parentMessage" />
@code {
private string parentMessage = "Initial value set in Parent";
private void ChangeValue()
{
parentMessage = $"Set in Parent {DateTime.Now}";
}
}
Shared/NestedChild.razor:
<div class="border rounded m-1 p-1">
<h2>Child Component</h2>
<p>Child Message: <b>@ChildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Child</button>
</p>
<NestedGrandchild @bind-GrandchildMessage="BoundValue" />
</div>
@code {
[Parameter]
public string ChildMessage { get; set; }
[Parameter]
public EventCallback<string> ChildMessageChanged { get; set; }
private string BoundValue
{
get => ChildMessage;
set => ChildMessageChanged.InvokeAsync(value);
}
private async Task ChangeValue()
{
await ChildMessageChanged.InvokeAsync(
$"Set in Child {DateTime.Now}");
}
}
Upozornění
Obecně se vyhněte vytváření komponent, které zapisují přímo do vlastních parametrů součásti. Předchozí komponenta místo přímého zápisu do svého parametru používá NestedChild BoundValue vlastnost ChildMessage . Další informace naleznete v tématu RazorASP.NET Core Součásti.
Shared/NestedGrandchild.razor:
<div class="border rounded m-1 p-1">
<h3>Grandchild Component</h3>
<p>Grandchild Message: <b>@GrandchildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Grandchild</button>
</p>
</div>
@code {
[Parameter]
public string GrandchildMessage { get; set; }
[Parameter]
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue()
{
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
}
}
Alternativní přístup vhodný ke sdílení dat v paměti a mezi komponentami, které nejsou nutně vnořené, najdete v tématu ASP.NET Core Blazor Správa stavu .
Další zdroje informací
Razor Komponenty poskytují funkce datových vazeb s @bind Razor atributem direktivy s polem, vlastností nebo hodnotou Razor výrazu.
Následující příklad vytvoří vazbu:
- Hodnota
<input>prvku pole jazykainputValueC#. - Druhá hodnota
<input>prvku vlastnosti jazykaInputValueC#.
Když prvek <input> ztratí fokus, aktualizuje se jeho vázané pole nebo vlastnost.
Pages/Bind.razor:
@page "/bind"
<p>
<input @bind="inputValue" />
</p>
<p>
<input @bind="InputValue" />
</p>
<ul>
<li><code>inputValue</code>: @inputValue</li>
<li><code>InputValue</code>: @InputValue</li>
</ul>
@code {
private string inputValue;
private string InputValue { get; set; }
}
Textové pole se v uživatelském rozhraní aktualizuje jenom při vykreslení komponenty, nikoli v reakci na změnu hodnoty pole nebo vlastnosti. Vzhledem k tomu, že se komponenty vykreslují po spuštění kódu obslužné rutiny události, změny polí a vlastností se obvykle projeví v uživatelském rozhraní ihned po aktivaci obslužné rutiny události.
Jako ukázku toho, jak se datová vazba sčítá v HTML, následující příklad naváže vlastnost na atributy InputValue a <input> druhého value onchange prvku. Druhým prvkem v následujícím příkladu je ukázka konceptu, která nemá navrhovat způsob vazby <input> dat v Razor komponentách.
Pages/BindTheory.razor:
@page "/bind-theory"
<p>
<label>
Normal Blazor binding:
<input @bind="InputValue" />
</label>
</p>
<p>
<label>
Demonstration of equivalent HTML binding:
<input value="@InputValue"
@onchange="@((ChangeEventArgs __e) => InputValue = __e.Value.ToString())" />
</label>
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string InputValue { get; set; }
}
Při vykreslení komponenty pochází element ukázky BindTheory HTML z vlastnosti value <input> InputValue . Když uživatel zadá hodnotu do textového pole a změní fokus prvku, událost se aktivuje a vlastnost se nastaví onchange InputValue na změněnou hodnotu. Ve skutečnosti je spouštění kódu složitější, protože @bind zpracovává případy, kdy se provádí převody typů. Obecně se aktuální hodnota výrazu přidruží k atributu a zpracovává @bind změny pomocí registrované obslužné value rutiny.
Vytvořte vazbu vlastnosti nebo pole u jiných model DOM (Document Object Model) (DOM) zahrnutím atributu s @bind:event="{EVENT}" událostí modelu DOM pro zástupný {EVENT} symbol. Následující příklad vytvoří vazbu vlastnosti na hodnotu prvku InputValue <input> při aktivaci oninput události prvku. Na rozdíl onchange od události, která se vyžádá, když prvek ztratí fokus, se při změně hodnoty oninput textového pole vyhodí.
Page/BindEvent.razor:
@page "/bind-event"
<p>
<input @bind="InputValue" @bind:event="oninput" />
</p>
<p>
<code>InputValue</code>: @InputValue
</p>
@code {
private string InputValue { get; set; }
}
Razor V vazbě atributů se rozlišují velká a malá písmena:
@bind``@bind:eventa jsou platné.@Bind/@Bind:Event(velká písmenaBEa ) nebo@BIND/@BIND:EVENT(všechna velká písmena) jsou neplatná.
Možnosti <select> elementu vazby na hodnoty objektů jazyka null C#
Neexistuje žádný rozumný způsob, jak reprezentovat hodnotu možnosti prvku <select> jako hodnotu objektu jazyka null C#, protože:
- Atributy HTML nemůže mít
nullhodnoty. Nejbližší ekvivalent vnullHTML je absence atributu HTML vvalue<option>elementu . - Při výběru objektu bez atributu prohlížeč považuje hodnotu za
<option>valuetextový obsah tohoto<option>elementu .
Rozhraní Blazor se nepokusí potlačit výchozí chování, protože by zahrnovalo:
- Vytvoření řetězce alternativních řešení pro zvláštní případy v rámci architektury
- Rozbíjení změn chování aktuální architektury
Při pokusu o dvousečtovou vazbu na hodnotu nezovládá rozhraní automaticky převody Blazor null <select> prázdných řetězců. Další informace najdete v tématu Oprava vazby na hodnotu null <select> (dotnet/aspnetcore #23221).
Nepochyitelné hodnoty
Když uživatel poskytne neopravitelnou hodnotu prvku vázaného na data, neopravitelná hodnota se při aktivaci události vazby automaticky vrátí na předchozí hodnotu.
Vezměte v úvahu následující komponentu, kde je prvek svázán s <input> int typem s počáteční hodnotou 123 .
Pages/UnparsableValues.razor:
@page "/unparseable-values"
<p>
<input @bind="inputValue" />
</p>
<p>
<code>inputValue</code>: @inputValue
</p>
@code {
private int inputValue = 123;
}
Vazba se ve výchozím nastavení vztahuje na událost onchange elementu. Pokud uživatel aktualizuje hodnotu položky textového pole na a změní fokus, hodnota elementu se vrátí, když se 123.45 123 onchange vyhodí. Když se hodnota zamítne ve prospěch původní hodnoty , uživatel pochopí, že jeho 123.45 123 hodnota nebyla přijata.
V případě události ( ) dojde k převrácení hodnoty po stisknutí klávesy, která zavádí oninput @bind:event="oninput" neopravitelnou hodnotu. Při cílení na událost s typem svázaným s objektem je uživateli znemožněn zadávání oninput int tečky ( . ). Tečka ( ) je okamžitě odebrána, takže uživatel obdrží okamžitou zpětnou vazbu, že . jsou povolena pouze celá čísla. Existují scénáře, kdy vrácení hodnoty události není ideální, například kdy by uživatel měl mít povoleno vymazat neopravitelnou oninput <input> hodnotu. Mezi alternativy patří:
- Nepoužívejte
oninputudálost . Použijte výchozí událost, kde se neplatná hodnota nevrátila,onchangedokud prvek neztratí fokus. - Vytvořte vazbu na typ s možnou hodnotou null, například nebo , a zadejte vlastní logiku a přístupový objekt pro
int?stringzpracování neplatnýchgetsetpoložek. - Použijte komponentu ověřování formuláře, například InputNumber<TValue> nebo InputDate<TValue> . Součásti ověřování formulářů poskytují integrovanou podporu pro správu neplatných vstupů. Součásti ověřování formulářů:
- Povolte uživateli zadání neplatného vstupu a příjem chyb ověření v přidruženém souboru EditContext .
- Zobrazovat chyby ověřování v uživatelském rozhraní bez toho, aby uživatel zasahoval do zadávání dalších dat webového formuláře.
Formátování řetězců
Datová vazba funguje s jedním DateTime formátovacím řetězcem pomocí @bind:format="{FORMAT STRING}" , kde zástupný symbol je {FORMAT STRING} formátovací řetězec. Jiné výrazy formátu, jako jsou formáty měn nebo čísel, nejsou v tuto chvíli dostupné, ale můžou být přidány v budoucí verzi.
Pages/DateBinding.razor:
@page "/date-binding"
<p>
<label>
<code>yyyy-MM-dd</code> format:
<input @bind="startDate" @bind:format="yyyy-MM-dd" />
</label>
</p>
<p>
<code>startDate</code>: @startDate
</p>
@code {
private DateTime startDate = new DateTime(2020, 1, 1);
}
V předchozím kódu je typ pole elementu <input> ( type atribut) ve výchozím nastavení text .
Podporují se System.DateTime hodnoty System.DateTimeOffset Nullable a :
private DateTime? date;
private DateTimeOffset? dateOffset;
Zadání formátu pro typ pole se nedoporučuje, protože má integrovanou podporu date Blazor formátování kalendářních dat. I přes doporučení používejte formát data pro vazbu, aby správně fungovala, pouze pokud je dodaný formát yyyy-MM-dd s date typem pole:
<input type="date" @bind="startDate" @bind:format="yyyy-MM-dd">
Vlastní formáty vazeb
Jazyk C# a get set přístupové objekty lze použít k vytvoření vlastního chování formátu vazby, jak ukazuje následující DecimalBinding komponenta. Komponenta vytvoří vazbu kladného nebo záporného desetinného čísla až se třemi desetinnými místy na <input> prvek pomocí vlastnosti ( string DecimalValue ).
Pages/DecimalBinding.razor:
@page "/decimal-binding"
@using System.Globalization
<p>
<label>
Decimal value (±0.000 format):
<input @bind="DecimalValue" />
</label>
</p>
<p>
<code>decimalValue</code>: @decimalValue
</p>
@code {
private decimal decimalValue = 1.1M;
private NumberStyles style =
NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
private CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
private string DecimalValue
{
get => decimalValue.ToString("0.000", culture);
set
{
if (Decimal.TryParse(value, style, culture, out var number))
{
decimalValue = Math.Round(number, 3);
}
}
}
}
Vazba s parametry komponenty
Běžným scénářem je vazba vlastnosti podřízené komponenty na vlastnost v její nadřazené komponentě. Tento scénář se nazývá zřetězovaná vazba, protože současně dochází k více úrovním vazby.
Parametry komponenty povolují vlastnosti vazby nadřazené komponenty se @bind-{PROPERTY} syntaxí, kde zástupný symbol je {PROPERTY} vlastnost, která se má svázat.
V podřízené komponentě nelze implementovat zřetězované vazby @bind se syntaxí. Obslužná rutina události a hodnota musí být zadány samostatně pro podporu aktualizace vlastnosti v nadřazené z podřízené komponenty.
Nadřazená komponenta stále využívá syntaxi k nastavení datové @bind vazby s podřízeným komponentou.
Následující ChildBind komponenta má parametr komponenty a Year EventCallback<TValue> . Podle konvence musí být parametr pro pojmenován jako název parametru komponenty EventCallback<TValue> s Changed příponou " ". Syntaxe pojmenování je {PARAMETER NAME}Changed , kde zástupný symbol je název {PARAMETER NAME} parametru. V následujícím příkladu EventCallback<TValue> má název YearChanged .
EventCallback.InvokeAsync vyvolá delegáta přidruženého k vazbě se poskytnutým argumentem a odešle oznámení události pro změněnou vlastnost.
Shared/ChildBind.razor:
<div class="card bg-light mt-3" style="width:18rem ">
<div class="card-body">
<h3 class="card-title">ChildBind Component</h3>
<p class="card-text">
Child <code>Year</code>: @Year
</p>
<button @onclick="UpdateYearFromChild">Update Year from Child</button>
</div>
</div>
@code {
private Random r = new Random();
[Parameter]
public int Year { get; set; }
[Parameter]
public EventCallback<int> YearChanged { get; set; }
private async Task UpdateYearFromChild()
{
await YearChanged.InvokeAsync(r.Next(1950, 2021));
}
}
Další informace o událostech EventCallback<TValue> a najdete v části EventCallback tohoto ASP.NET Core Blazor zpracování událostí článku.
V následující Parent komponentě year je pole vázané na parametr podřízené Year komponenty. Parametr Year je možné svázat, protože má doprovodnou YearChanged událost, která odpovídá typu Year parametru.
Pages/Parent.razor:
@page "/Parent"
<h1>Parent Component</h1>
<p>Parent <code>year</code>: @year</p>
<button @onclick="UpdateYear">Update Parent <code>year</code></button>
<ChildBind @bind-Year="year" />
@code {
private Random r = new Random();
private int year = 1979;
private void UpdateYear()
{
year = r.Next(1950, 2021);
}
}
Podle konvence může být vlastnost svázaná s odpovídající obslužnou rutinou události zahrnutím atributu přiřazeného obslužné rutině, kde zástupný symbol @bind-{PROPERTY}:event {PROPERTY} je vlastnost . <ChildBind @bind-Year="year" /> je ekvivalentem zápisu:
<ChildBind @bind-Year="year" @bind-Year:event="YearChanged" />
V sofistikovanějším příkladu z reálného světa se používá následující PasswordEntry komponenta:
- Nastaví
<input>hodnotu prvku napasswordpole. - Zpřístupňuje změny vlastnosti nadřazené komponentě pomocí objektu , který předává aktuální hodnotu podřízeného pole
PasswordEventCallbackjako svůjpasswordargument. - Použije
onclickudálost k aktivaciToggleShowPasswordmetody . Další informace naleznete v tématu ASP.NET Core Blazor zpracování událostí.
Shared/PasswordEntry.razor:
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
</p>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
</div>
</div>
@code {
private bool showPassword;
private string password;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private async Task OnPasswordChanged(ChangeEventArgs e)
{
password = e.Value.ToString();
await PasswordChanged.InvokeAsync(password);
}
private void ToggleShowPassword()
{
showPassword = !showPassword;
}
}
Komponenta PasswordEntry se používá v jiné komponentě, například v následujícím PasswordBinding příkladu komponenty.
Pages/PasswordBinding.razor:
@page "/password-binding"
<h1>Password Binding</h1>
<PasswordEntry @bind-Password="password" />
<p>
<code>password</code>: @password
</p>
@code {
private string password = "Not set";
}
Při PasswordBinding počátečním vykreslení komponenty se v uživatelském rozhraní password zobrazí hodnota Not set . Po počátečním vykreslení hodnota odráží změny provedené v hodnotě parametru komponenty password Password v PasswordEntry komponentě.
Poznámka
Předchozí příklad vytvoří vazbu hesla jedním směrem z podřízené komponenty na PasswordEntry nadřazenou PasswordBinding komponentu. Dvousměnná vazba není v tomto scénáři požadavkem, pokud je cílem aplikace mít sdílenou komponentu pro zadávání hesel, aby ji bylo možné opakovaně používat v aplikaci, která pouze předává heslo nadřazenému serveru. Přístup, který umožňuje dvoucestné vazby bez přímého zápisu do parametru podřízené komponenty ,najdete v příkladu komponenty v části Vázání napříč více než dvěma součástmi NestedChild tohoto článku.
Provádění kontrol nebo zachytání chyb v obslužné rutině Následující revidovaná komponenta poskytuje uživateli okamžitou zpětnou vazbu, pokud se v hodnotě hesla používá PasswordEntry mezera.
Shared/PasswordEntry.razor:
<div class="card bg-light mt-3" style="width:22rem ">
<div class="card-body">
<h3 class="card-title">Password Component</h3>
<p class="card-text">
<label>
Password:
<input @oninput="OnPasswordChanged"
required
type="@(showPassword ? "text" : "password")"
value="@password" />
</label>
<span class="text-danger">@validationMessage</span>
</p>
<button class="btn btn-primary" @onclick="ToggleShowPassword">
Show password
</button>
</div>
</div>
@code {
private bool showPassword;
private string password;
private string validationMessage;
[Parameter]
public string Password { get; set; }
[Parameter]
public EventCallback<string> PasswordChanged { get; set; }
private Task OnPasswordChanged(ChangeEventArgs e)
{
password = e.Value.ToString();
if (password.Contains(' '))
{
validationMessage = "Spaces not allowed!";
return Task.CompletedTask;
}
else
{
validationMessage = string.Empty;
return PasswordChanged.InvokeAsync(password);
}
}
private void ToggleShowPassword()
{
showPassword = !showPassword;
}
}
Vytvoření vazby mezi více než dvěma komponentami
Parametry můžete svázat s libovolným počtem vnořených komponent, ale musíte respektovat jednosměnné toky dat:
- Oznámení o změně se chytou nahoru v hierarchii.
- Nové hodnoty parametrů prochádí hierarchii .
Běžným a doporučeným přístupem je ukládat pouze podkladová data v nadřazené komponentě, aby nedocházelo k nejasnostem o tom, jaký stav je třeba aktualizovat, jak je znázorněno v následujícím příkladu.
Pages/Parent.razor:
@page "/parent"
<h1>Parent Component</h1>
<p>Parent Message: <b>@parentMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Parent</button>
</p>
<NestedChild @bind-ChildMessage="parentMessage" />
@code {
private string parentMessage = "Initial value set in Parent";
private void ChangeValue()
{
parentMessage = $"Set in Parent {DateTime.Now}";
}
}
Shared/NestedChild.razor:
<div class="border rounded m-1 p-1">
<h2>Child Component</h2>
<p>Child Message: <b>@ChildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Child</button>
</p>
<NestedGrandchild @bind-GrandchildMessage="BoundValue" />
</div>
@code {
[Parameter]
public string ChildMessage { get; set; }
[Parameter]
public EventCallback<string> ChildMessageChanged { get; set; }
private string BoundValue
{
get => ChildMessage;
set => ChildMessageChanged.InvokeAsync(value);
}
private async Task ChangeValue()
{
await ChildMessageChanged.InvokeAsync(
$"Set in Child {DateTime.Now}");
}
}
Upozornění
Obecně se vyhněte vytváření komponent, které zapisují přímo do vlastních parametrů součásti. Předchozí komponenta místo přímého zápisu do svého parametru používá NestedChild BoundValue vlastnost ChildMessage . Další informace naleznete v tématu RazorASP.NET Core Součásti.
Shared/NestedGrandchild.razor:
<div class="border rounded m-1 p-1">
<h3>Grandchild Component</h3>
<p>Grandchild Message: <b>@GrandchildMessage</b></p>
<p>
<button @onclick="ChangeValue">Change from Grandchild</button>
</p>
</div>
@code {
[Parameter]
public string GrandchildMessage { get; set; }
[Parameter]
public EventCallback<string> GrandchildMessageChanged { get; set; }
private async Task ChangeValue()
{
await GrandchildMessageChanged.InvokeAsync(
$"Set in Grandchild {DateTime.Now}");
}
}
Alternativní přístup vhodný ke sdílení dat v paměti a mezi komponentami, které nejsou nutně vnořené, najdete v tématu ASP.NET Core Blazor Správa stavu .