#c# #asp.net-core #blazor
Вопрос:
У меня есть аналогичный компонент, и я хочу сохранить экземпляр InnerComponent
при первом его отображении и каждый раз отображать один и тот же экземпляр без его восстановления.
@if(isVisible)
{
<InnerComponent @ref="@_InnerComponent" @key="@("InnerComponentKey")">
@ChildContent
</InnerComponent>
}
@code{
[Parameter] public InnerComponent _InnerComponent { get; set; }
private bool IsVisible { get; set; }
}
Когда внутренний компонент виден, пользователь может управлять его состоянием.
Но если IsVisible
будет установлено значение false, а затем снова true, внутренний компонент будет переопределен _InnerComponent
повторно, и, таким образом, мы потеряем отслеживание изменений, внесенных пользователем в этот InnerComponent
экземпляр.
Добавление @key, похоже, также не помогает сохранить экземпляр. Он просто перезаписывается и перезаписывается :/ Я уверен, что я передаю ему один и тот же ключ оба раза, когда он отображается, но я не знаю, как проверить ключи, с которыми он сравнивается.
Если возможно визуализировать экземпляр компонента, я мог бы сделать что-то вроде следующего, но, похоже, я не могу найти способ сделать это.
@if(isVisible)
{
@if(_InnerComponent == null)
{
<InnerComponent @ref="@_InnerComponent" @key="@("InnerComponentKey")">
@ChildContent
</InnerComponent>
}
else
{
@_InnerComponent.Render()
}
}
Я принимаю критику по своему вопросу, так как я не задавал много вопросов 🙂
Заранее спасибо!
Упрощенный пример:
Допустим , у нас есть следующий компонент, который я собираюсь назвать «Контрконтейнер», где «<Счетчик> » — это компонент счетчика из шаблона проекта Blazor по умолчанию.
@if(CounterIsVisible)
{
<Counter @ref="@_Counter" @key="@("CounterKey")" />
}
<button @onclick="() => CounterIsVisible = !CounterIsVisible">
Show/Hide counter
</button>
@code{
[Parameter] public Counter _Counter { get; set; }
private bool CounterIsVisible { get; set; } = true;
}
Я хочу сохранить _Counter
экземпляр, чтобы увидеть правильный _Counter.currentCount
, на который я рассчитывал. Я мог бы сохранить его, используя метод из этой статьи, но я нахожу их все непрактичными, потому что
- компонент, который я создаю, содержит гораздо больше данных, чем просто одна переменная
- Мне нужны данные только до тех пор, пока
CounterContainer
они существуют, и только для визуализации - Это просто слишком сложно для моего варианта использования
У меня уже есть Counter
ссылка, сохраненная. Я просто хочу просмотреть его вместо того, чтобы восстанавливать и перезаписывать все это.
Надеюсь, это немного прояснило ситуацию (:
Ответ №1:
Я удивлен, что он компилируется, так как вы неправильно написали свой класс компонентов:
[Parameter] public **InnerCopmonent** _InnerComponent { get; set; }
Почему у вас вообще есть @ref для вашего внутреннего компонента? Что делает внутренний компонент и почему вы хотите ссылаться на него? Можете ли вы поделиться кодом этого компонента?
Комментарии:
1. Привет @Bennyboy1973, спасибо за ответ 🙂 Я не вставлял никакого реального кода, поэтому я предполагаю, что этот точный пример (теперь отредактированный) не будет компилироваться.
2. Я добавил
@ref
, хотя это не на 100% относится к вопросу, потому что мне это нужно в моем коде, и я заметил, что@key
и@ref
иногда странно взаимодействую. Я чувствую, что это не добавляет много шума, но кто-то опытный мог бы заметить, если есть проблемы с использованием обоих.3. Компонент просто слишком длинный, чтобы вставить его в этот вопрос, но я просто отредактировал дополнительный пример. Надеюсь, это несколько прояснит мой вопрос 🙂
Ответ №2:
- лучший вариант: отдельное представление и данные. Состояние, которое вы хотите сохранить, должно храниться не внутри компонента, а в отдельном объекте (ViewModel).
- краткое решение: всегда визуализируйте компонент. Используйте @isVisible для включения/выключения css-класса, чтобы скрыть его.
Комментарии:
1. Мне нравится твой первый вариант. Второй вариант кажется своего рода анти-Блейзором, и мне кажется, что его худший грех в том, что он сработает, и операция может просто сделать это с этого момента.
2. Да, первый вариант хорош, и у меня уже есть отдельный вид и модель данных. Просто информация, которую я пытаюсь сохранить, относится к модели представления (
Counter
компоненту), а не к модели данных. Я не думал об использовании ccs, но я не знаю, то ли это решение, которое я ищу. Тем не менее, спасибо за предложения!
Ответ №3:
Мне нравится делать такие вещи, чтобы создать класс переноса, который я создаю в родительском экземпляре и передаю ребенку как Parameter
. Поскольку класс передается по ссылке, мне не нужно беспокоиться о событиях или чем-то подобном. (Я только что придумал класс для демонстрации, чтобы показать, что в нем может быть все, что вы хотите)
CounterData.cs
public class CounterData
{
public int counter { get; set; }
public string Title { get; set; } = "Counter";
public List<int> CounterHistory { get; set; } = new List<int>();
}
Контрконтейнер.бритва
@page "/counter"
<h3>Counter Container</h3>
<button @onclick="()=> ShowCounter=!ShowCounter">Toggle</button>
@if (ShowCounter)
{
<Counter CarryingInstance="PersistentData" />
}
@code {
CounterData PersistentData = new CounterData();
bool ShowCounter = false;
}
Счетчик.бритва
<h3>@CarryingInstance.Title</h3>
<input @bind="CarryingInstance.Title" /><br />
<button @onclick="()=> Increment(1)">Add</button>
<button @onclick="()=>Increment(-1)">Sub</button>
@CarryingInstance.counter <br />
History:
@foreach (var item in CarryingInstance.CounterHistory)
{
<span>amp;nbsp; @item</span>
}
@code {
[Parameter]
public CounterData CarryingInstance { get; set; }
void Increment (int amount)
{
CarryingInstance.counter = amount;
CarryingInstance.CounterHistory.Add(CarryingInstance.counter);
}
}
Комментарии:
1. Спасибо за подробный ответ! У меня действительно есть класс , похожий на
CounterData
, но информация, которую я пытаюсь сохранить, на самом деле принадлежит неCounterData
объекту, а скорееCounter
компоненту (это просто визуальные данные с той же областью действия, что и «ConterContainer»).
Ответ №4:
Я видел возможность скрыть компонент с помощью CSS и неожиданные проблемы, которые это может вызвать, потому что компоненты затем не проходят через обычные события жизненного цикла, когда они законно перенаправляются/восстанавливаются. Поэтому я занят обновлением нескольких компонентов, чтобы исправить именно это. Мой совет состоял бы в том, чтобы по возможности избегать этого.
Другой способ, аналогичный методу экземпляра BennyBoys, заключается в том, что вы, вероятно, могли бы сделать это, используя внедрение зависимостей и зарегистрировав тип в качестве службы с областью действия или одноэлементной службы и внедрив его в компонент.
Вы можете прочитать здесь, в блоге Криса Сейнти, о том, как работают различные регистрации в blazor, и их поведении, и если это будет соответствовать вашим потребностям.
https://chrissainty.com/service-lifetimes-in-blazor/
Я бы еще раз проверил через официальные документы, что они все еще ведут себя так же, хотя на всякий случай, но это может быть хорошим способом сделать это. Я думаю, что это зависит от того, каков ваш фактический вариант использования, хорошая ли идея делать это так, но это другой вариант 🙂
Комментарии:
1. Да, но я определенно не хочу регистрировать эти данные в сервисе. Это просто слишком сложно для моего варианта использования :/ Спасибо за предложение, хотя!