#blazor #blazor-server-side
#blazor #blazor-на стороне сервера
Вопрос:
У меня есть следующий компонент, который напоминает TextBox
компонент. Однако по какой-то причине содержимое Value
, похоже, никогда не меняется.
Я бы ожидал, что это будет работать с привязкой данных без ручного JavaScript, нет?
<div class="form-group">
<input type="text" class="form-control" @bind="Value" @onkeyup="OnKeyUp" placeholder="@Placeholder"/>
</div>
@code {
[Parameter]
public string Value { get; set; }
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
[Parameter]
public string Placeholder { get; set; }
private void OnKeyUp(KeyboardEventArgs obj)
{
ValueChanged.InvokeAsync(Value);
}
}
Ответ №1:
Вы не должны привязываться к a [Parameter]
, поскольку это может вызвать побочные эффекты (см. Комментарий Стива Сандерсона здесь )
Похоже, вы хотите двустороннюю привязку к каждому изменению, для чего я бы использовал oninput
вместо onkeyup
, но вы можете использовать onkeyup
, если это действительно то, что вам нужно.
Главное — привязаться к локальному и никогда не изменять общедоступный параметр вручную:
<div class="form-group">
<input type="text" class="form-control"
@bind-value=@InternalValue
@bind-value:event="oninput"
placeholder="@Placeholder"/>
</div>
@code {
string InternalValue
{
get => Value;
set
{
if (value!=Value)
{
ValueChanged.InvokeAsync(value);
}
}
}
[Parameter]
public string Value { get; set; }
[Parameter]
public EventCallback<string> ValueChanged { get; set; }
[Parameter]
public string Placeholder { get; set; }
}
Редактировать: добавление заметок Стива Сандерсона на случай, если они исчезнут…
Цитата Стива Сандерсона по проблеме GitHub, связанной выше:
Хорошо, я посмотрел более подробно и посмотрел, что происходит. Ниже приведено объяснение, но прежде чем перейти к этому, я повторю свое утверждение о том, что основная проблема заключается в том, что дочерний компонент перезаписывает свое собственное значение свойства [Parameter] . Избегая этого, вы можете избежать этой проблемы.
В этом случае и в других Blazor полагается на безопасное назначение параметров от родителя к потомку (не перезаписывает информацию, которую вы хотите сохранить) и не имеет побочных эффектов, таких как запуск большего количества рендеров (потому что тогда вы можете оказаться в бесконечном цикле). Вероятно, нам следует усилить руководство в документах, а не просто сказать «не записывайте свои собственные параметры», а расширить его, чтобы предостеречь от побочных эффектов в таких установщиках свойств. Использование Blazor свойств C # для представления канала связи между родительскими и дочерними компонентами довольно удобно для разработчиков и хорошо смотрится в исходном коде, но возможность побочных эффектов проблематична. У нас уже есть анализатор времени компиляции, который предупреждает, если у вас нет правильных модификаторов доступности для свойств [Parameter] — возможно, нам следует расширить его, чтобы выдавать предупреждения / ошибки, если параметр является чем-то иным, кроме простого свойства { get; set; } auto .
Итак, в этом случае решение довольно простое: замените свойство значения Component1 на простое { get; set; } , и вместо того, чтобы пытаться записать в него, пусть Component1 реагирует на нажатия кнопок, вызывая valueChanged . Тогда у вас нет никакого рекурсивного цикла рендеринга, и перезапись данных не происходит.
private void DecrementValue() { //Value--; <-- Don't do this // Do this instead: ValueChanged.InvokeAsync(Value - 1); }
Комментарии:
1. Начиная с .NET 7, вы получите предупреждение компилятора BL0007, если параметр компонента не является свойством auto. Решение в этом ответе помогло мне избавиться от этого предупреждения, поскольку свойство internalValue не является параметром.