Как реализовать несколько тем в приложении BlazorWasm

Ранее на этой неделе Дэниел Рот опубликовал последние обновления обновлений ASP.NET Core и Blazor в .NET Core 3.0 в своем блоге https://devblogs.microsoft.com/aspnet/asp-net-core -and-blazor-updates-in-net-core-3-0 .

Я был взволнован, поскольку NET Core 3.0 готов к производству, и предварительное обновление Blazor WebAssembly доступно в этом выпуске, а также смотрел презентации Дэниела Рота на .NET Conf 2019:

Создание полнофункциональных веб-приложений C # с помощью Blazor в .NET Core 3.0 День 1 на .NET Conf 2019

Будущее Blazor на стороне клиента, день 2 на .NET Conf 2019

Браузер + Razor = Blazor!

В этой статье я собираюсь продемонстрировать свое первое экспериментальное приложение Blazor для примера использования:

Как реализовать несколько тем в приложении BlazorWasm.

Темы определяют внешний вид веб-приложения, которое по умолчанию находится в каталоге / themes. Каждая тема представлена ​​в отдельном каталоге, она может содержать макет, страницы, компоненты… в этой статье мы рассмотрим несколько характеристик:

  • Возможность добавлять новую тему и легко ее активировать
  • Тема имеет независимый макет, другое меню навигации, разные страницы, разные компоненты… и т. Д. Но она может использовать одни и те же серверные API.
  • Определить новую тему необходимо, чтобы она соответствовала структуре приложения и была совместима с маршрутами, моделями, внутренними API-интерфейсами… и т. Д.

Однако сначала мы начнем этот пример с разговора о шаблоне Blazor weather, который мы просматриваем из поколения netcorecli.

Давайте посмотрим, что сгенерирован шаблон проекта:

dotnet new blazorwasm -o blazor-dynamic-themes-sample
The template "Blazor WebAssembly App" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on /Users/kelvin.binh/sd/blazor-dynamic-themes-sample/blazor-dynamic-themes-sample.csproj...
  Restore completed in 8.4 sec for /Users/kelvin.binh/sd/blazor-dynamic-themes-sample/blazor-dynamic-themes-sample.csproj.
Restore succeeded.
.
├── App.razor
├── Pages
│   ├── Counter.razor
│   ├── FetchData.razor
│   └── Index.razor
├── Program.cs
├── Shared
│   ├── MainLayout.razor
│   ├── NavMenu.razor
│   └── SurveyPrompt.razor
├── Startup.cs
├── _Imports.razor
├── blazor-dynamic-themes-sample.csproj
├── obj
│   ├── blazor-dynamic-themes-sample.csproj.nuget.cache
│   ├── blazor-dynamic-themes-sample.csproj.nuget.dgspec.json
│   ├── blazor-dynamic-themes-sample.csproj.nuget.g.props
│   ├── blazor-dynamic-themes-sample.csproj.nuget.g.targets
│   └── project.assets.json
└── wwwroot
    ├── css
    │   ├── bootstrap
    │   ├── open-iconic
    │   └── site.css
    ├── index.html
    └── sample-data
        └── weather.json

Теперь мы собираемся настроить структуру проекта для нескольких тем в приложении, примерно так:

.
├── App.razor
├── AppState.cs
├── Models
│   ├── Settings.cs
│   └── Weather.cs
├── Program.cs
├── RouteView
│   ├── NavigationView.razor
│   └── RouteView.razor
├── Startup.cs
├── Themes
│   ├── Default
│   │   ├── Dashboard.razor
│   │   ├── MainLayout.razor
│   │   ├── NavMenu.razor
│   │   └── NewsFeed.razor
│   ├── RainyDay
│   │   ├── Dashboard.razor
│   │   ├── MainLayout.razor
│   │   ├── NavMenu.razor
│   │   └── WeatherSummary.razor
│   └── Redwood
│       ├── Dashboard.razor
│       ├── MainLayout.razor
│       ├── NavMenu.razor
│       └── Temperature.razor
├── _Imports.razor
├── blazor-dynamic-themes-sample.csproj
└── wwwroot
    ├── css
    │   ├── bootstrap
    │   ├── open-iconic
    │   └── site.css
    ├── index.html
    └── sample-data
        ├── settings.json
        └── weather.json

Корневой компонент

Приложению BlazorWasm требуется по крайней мере один компонент, называемый корневым компонентом. Все остальные компоненты будут находиться в App.razor в качестве основного корневого компонента.

Маршруты

Компонент маршрутизатора отображается в корневом компоненте, файле App.razor.

Компонент маршрута указывает шаблон Найдено, если запросы обнаружены, и шаблон NotFound, если запросы не найдены.

Во время выполнения компонент RouteView:

- Получает RouteData от Router вместе с любыми желаемыми параметрами.

- Визуализирует указанный компонент с его макетом (или необязательным макетом по умолчанию) с использованием указанных параметров.

Вы можете дополнительно указать параметр DefaultLayout с классом макета, который будет использоваться для компонентов, которые не указывают макет. В шаблонах Blazor по умолчанию указан компонент MainLayout.

Https://docs.microsoft.com/en-us/aspnet/core/blazor/routing?view=aspnetcore-3.0#route-templates

Идея указать динамический макет для указания имени темы, нам нужно указать неявное пространство имен для метода @ Type.GetType, например:

<RouteView RouteData="@routeData" DefaultLayout="@Type.GetType(string.Format(themeSelected, _appState.ActiveTheme))" />

Чтобы вычислить динамическое пространство имен для выбранной темы, нам необходимо внедрить AppState как контейнер состояния для приложения.

Внедрение зависимости

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

Запросите службу AppState в компоненте RouteView с помощью директивы Razor @inject.

Государственный контейнер

В приложении AppState представляет собой простой класс, внедренный как одноэлементный сервис. Можно управлять и координировать многие компоненты во всех приложениях.

  • Свойство ActiveTheme - это текущая выбранная тема, «По умолчанию» - имя по умолчанию.
  • OnChange, к нему привязано StateHasChanged ().
  • Метод SetTheme заключается в изменении ActiveTheme и запускает событие OnChange.

RouterView выберите динамический тип из атрибута DefaultLayout и повторно визуализируйте фрагмент для дочернего компонента.

Вставьте экземпляр HttpClient с помощью директивы @inject и запросите API в методе OnInitializedAsync для выполнения асинхронной операции, затем SetTheme метод вызывается для обновления ActiveTheme, а затем запускает событие OnChange.

RenderFragment

Уведомляет компонент об изменении его состояния

StateHasChanged вызывается для повторной визуализации компонента, когда выбирается новая ActiveTheme, нет необходимости вручную вызывать StateHasChanged (). Он вызывается автоматически для повторной визуализации ParentComponent, так же как дочерние события запускают повторную визуализацию компонента в обработчиках событий, которые выполняются внутри дочернего элемента.

Заключение

Реализация нескольких тем в CMS сложнее, чем в этом приложении. В этой статье мы продемонстрировали эту функцию в простом приложении BlazorWasm. Мы не вдавались во все функции Blazor, но, надеюсь, этого было достаточно, чтобы подогреть ваш аппетит и узнать больше о Blazor, WebAssembly, .NET Core.

Все примеры кода из этой статьи доступны в GitHub.

Спасибо за прочтение! Меня зовут Кельвин Бинь, я программист полного цикла в НашТек, я делаю все возможное, чтобы предоставить точную информацию, но если вы видите ошибку, дайте мне знать.

Если вы хотите получить уведомление, когда я напишу новую статью, введите здесь свой адрес электронной почты.