Я хочу проверить, можно ли динамически создавать компоненты Blazor.
Я не могу найти способ сделать это. Я немного поэкспериментировал с некоторым динамическим контентом, найденным на эта ссылка, но не дал никаких результатов.
Извините за поздний ответ - ваш ответ покрывает мои потребности, спасибо.
Для версии 0.2 это ответ Стива Сандерсона:
We'll implement nicer APIs to build RenderFragments in the future, but for now you can
@CreateDynamicComponent(); @functions { RenderFragment CreateDynamicComponent() => builder => { builder.OpenComponent(0, typeof(SurveyPrompt)); builder.AddAttribute(1, "Title", "Some title"); builder.CloseComponent(); }; }
Those are very low-level APIs (not even documented) so we hope not many people need to do this right now. Higher-level APIs for this will come later.
Найдено здесь
«Мы надеемся, что это понадобится не многим» - что ж, любое дизайнерское приложение должно иметь возможность динамически добавлять компоненты. Редакторы WYSIWYG, пользовательский интерфейс моделирования процессов, пользовательский интерфейс приборной панели ... так что это не редкое и внеземное требование ...
Возможно, это низкий уровень, но в нем есть документация RenderTreeBuilder.OpenComponent - метод
Судя по комментариям к принятому ответу и исходной версии этого ответа, я думаю, что может возникнуть небольшая путаница с динамическим добавлением компонентов. Есть (по крайней мере) несколько способов добиться этого (и ряд существующих вопросов по этому поводу, например, здесь). Все зависит от того, что именно вы подразумеваете под «динамически»:
Если вы пытаетесь просто показать или скрыть компоненты на основе некоторого состояния в ваших данных или модели, то «нормальный» способ динамического рендеринга компонента - это использовать какой-то условный код в вашем представлении Razor.
@if (_showCounter)
{
<MyCounterComponent Count = "@_count" />
}
@code {
bool _showCounter = true;
int _count;
}
Для повторяющихся наборов данных, таких как списки элементов, вы можете воспользоваться привязкой данных Blazor.
Возьмем пример страницы / компонента, которая показывает заказ на продажу, а затем имеет дочерний компонент для каждой строки заказа на продажу. У вас на странице с бритвой может быть такой код:
@foreach (var salesOrderLine in _salesOrder.salesOrderlines)
{
<SalesOrderLine SOLine=@salesOrderLine />
};
Если бы у вас была кнопка, которая добавляла другую строку заказа на продажу, вы могли бы просто добавить новую запись в модель / модель представления _salesOrder
в этом событии нажатия кнопки.
Щелчки по кнопке обычно вызывают повторный рендеринг, поэтому на странице должен автоматически отображаться дополнительный компонент SalesOrderLine
(и если этого не происходит, вы можете использовать this.StateHasChanged();
, чтобы сообщить ему, что все по-другому и вызвать повторный рендеринг)
Если ваш список содержит разные типы, вы можете использовать оператор switch, чтобы решить, какой тип компонента отображать, например (из этот вопрос GitHub):
<ul> @foreach (fruit in fruits) { switch(fruit) { case PearComponent p: <PearComponent ParameterOfSomeSort = "p"></PearComponent> <li>Or render pears like this, if you want the li in it</li> break; case AppleComponent a: <AppleComponent></AppleComponent> break; case BananaComponent b: <BananaComponent></BananaComponent> break; case RaspberryComponent r: <RaspberryComponent></RaspberryComponent> break; } } </ul>
Есть некоторые случаи, с которыми нельзя хорошо справиться с использованием подхода Razor, описанного выше. В этих случаях RenderFragment
предлагает другой способ динамической визуализации частей страницы.
Если у вас действительно полиморфный список (например, список объектов, которые реализуют один и тот же интерфейс или наследуются от одного и того же класса), тогда можно использовать такой подход из этого сообщения GitHub:
@page "/" @foreach (CounterParent counter in components) { RenderFragment renderFragment = (builder) => { builder.OpenComponent(0, counter.GetType()); builder.CloseComponent(); }; <div> <div>Before the component</div> @renderFragment <div>Afterthe component</div> </div> } @code { List<CounterParent> components = new List<CounterParent>() { new CounterParent(), new CounterChild() }; }
Команда Blazor - это рассмотрение улучшения того, как обрабатываются полиморфные списки в Blazor:
mkArtakMSFT commented on 1 Oct 2019 Thanks for contacting us, @Joebeazelman. Using the switch approach you have will be our recommendation. We will consider doing something better in this area in the future.
Ключевым моментом здесь (для тех, кто имеет фон MVC) является то, что нет необходимости пытаться вручную ввести новый HTML в DOM или динамически загружать частичное представление, как вы могли бы в MVC, Blazor сделает это для ты.
Несмотря на сходство синтаксиса между страницами razor для MVC и для Blazor, модель Blazor концептуально намного ближе к чему-то вроде React, чем к MVC, очень важно понимать, что в фоновом режиме есть что-то вроде теневой DOM .
На этой странице есть хорошие указатели о привязке данных в Blazor.
Какие?! Динамическая визуализация компонентов невероятно полезна и очень распространена. Как бы вы, например, обработали полиморфный список компонентов, в котором каждый член реализует свое собственное уникальное визуальное представление, которое не может быть определено во время компиляции, поскольку они могут быть внешними компонентами подключаемого модуля? В этом сценарии ваш подход терпит неудачу.
Привет, @ATL_DEV. Вероятно, это немного зависит от того, насколько широко или узко определение «динамический». Я обновил свой ответ, чтобы попытаться сделать его более ясным. Я, конечно, согласен, что это очень полезное средство, но лично я бы не сказал, что оно было настолько распространенным, например, мы только что написали крупное бизнес-приложение на Blazor и ни разу не использовали RenderFragment
. Сценарий полиморфного рендеринга внешних плагинов определенно был бы отличным использованием RenderFragment
. Кстати, команда Blazor хочет улучшить полиморфную обработку, см. Ссылку на github в моем ответе.
Пожалуйста, добавьте больше вашего варианта использования и кода, чего именно вы пытаетесь достичь? Что вы пробовали, и где это не удается?