Blazor Wasm — Как обновить базовые компоненты из унаследованного компонента?

У меня есть приложение Blazor Wasm с двумя компонентами:

Базовая комп.бритва:

<h1>I'm base - @Text</h1>

@code{
    protected string Text {get; set;} = "Default";
}

ChildComponent.razor

@inherits BaseComp

<BaseComp/>

<h1>Hello, only child text!</h1>

@code {
    protected override void OnInitialized()
    {
        Text = "new";
    }
}

и на странице будет отображаться следующее:

I'm base - Default
Hello, only child text!

Как я могу обновить свойство Text базового компонента из дочернего компонента?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
94
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вам нужно будет объявить его как параметр и передать значение вниз.

Базовая комп.бритва:

<h1>I'm base - @Text</h1>

@code{
   [Parameter] public string Text {get; set;} = "Default";
}

ChildComponent.razor

<BaseComp Text = "Text"/>

<h1>Hello, only child text!</h1>

@code {
    protected override void OnInitialized()
    {
        Text = "new";
    }
}

Это работает, когда я определяю свойство дочернего компонента, которое будет передано базовому компоненту, но есть ли другой способ добиться этого? Для нескольких параметров это может стать довольно подробным, потому что мне нужно определить одни и те же свойства как для базы, так и для дочернего элемента.

Florent 15.11.2022 16:34

К сожалению нет. Обычный способ сделать это — создать собственный класс, который содержит ваши свойства и передать этот экземпляр вниз.

Marvin Klein 15.11.2022 16:35

@HenkHolterman да, ты прав. Я удалил его.

Marvin Klein 15.11.2022 16:45
Ответ принят как подходящий

С этим фрагментом кода

@inherits BaseComp
<BaseComp/>  @* a new instance, not inheritance *@

Вы наследуете и сочиняете с помощью BaseComp. Вы не используете часть наследования.

Поэтому используйте только композицию и следуйте ответу @MarvinKlein, но удалите строку @inherits. Или изменить код на:

@inherits BaseComp

@*<BaseComp />*@
@{ base.BuildRenderTree(__builder); }

<h1>Hello, only child text!</h1>

Я хочу использовать базовый компонент для отображения одной и той же сетки на всех страницах, но с некоторой дополнительной логикой. Решение @MarvinKlein и ваша работа, есть ли какие-либо недостатки при использовании метода BuildRenderTree?

Florent 15.11.2022 16:47

Я хочу использовать базовый компонент для отображения одной и той же сетки на всех страницах, но с некоторой дополнительной логикой.

Тип шаблона, для которого текущий ComponentBase не предназначен.

Вы также можете:

  1. Используйте другой базовый компонент, предназначенный для этого.
  2. Заставьте это работать с ComponentBase.

Вот как заставить его работать с ComponentBase, поскольку описание того, как создать другой компонент, выходит за рамки ответа SO.

Наш компонент-обертка:

<h3 class = "text-primary m-2 p-2">Wrapper</h3>
<div class = "bg-primary text-white m-2 p-2">
@this.Body
</div>

@code {
    protected abstract RenderFragment? Body { get; }
}

И файл кода программной части, чтобы сделать его абстрактным.

public abstract partial class Wrapper { }

Наш новый Index. Ключевым моментом здесь является то, что наш контент больше не находится в верхнем блоке — разделе, которому соответствует компилятор Razor BuildRenderTree. Вместо этого мы определяем его в отдельном RenderFragment.

Теперь наш верхний блок содержит свойство RenderFragment, которому мы присвоили метод this.Body базового класса, содержащий скомпилированный код из шаблона.

@page "/"
@inherits Wrapper

@this.Content

@code {
    // Where we put the base Template class Render Fragment
    private RenderFragment Content;

    // Ctor - must call base and then we load the base Template class content
    public Index() : base()
        => this.Content = (builder) => base.BuildRenderTree(builder);

    // Our content that the Razor compiler will build in Body
    // __builder is the built in Razor compiler RenderTreeBuilder 
    protected override RenderFragment Body => (__builder) =>
    {
        <PageTitle>Index</PageTitle>

        <h1>Hello, world!</h1>

        <div>Welcome to your new app.</div>

        <SurveyPrompt Title = "How is Blazor working for you?" />
    };
}

Вот как это выглядит:

Чтобы не было путаницы, я переименовал его в Wrapper. Это просто демонстрация, чтобы показать, как вы можете сделать это с небольшими хитростями кода. Это определенно не защита от дурака. Я использую эту технику, но с совершенно другим компонентом Wrapper.

MrC aka Shaun Curtis 16.11.2022 19:09

Другие вопросы по теме