Переключение тем с помощью Javascript Interop в Blazor

· 4 мин чтения

Для таких людей, как я, которые страдают от воспоминаний каждый раз, когда я открываю веб-страницу, я придумал очень простое решение, как переключаться между светлым и темным режимами с помощью Javascript и вызывать его из Blazor с помощью Javascript Interop.

Установка родительского атрибута

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

Чтобы сделать это в Javascript, нам нужно будет запустить эту команду

[[[ТОК_1]]]

В нашем случае мы хотим иметь два идентификатора для каждого типа стиля: light и dark.

Создание файла Javascript для обработки логики

Теперь у нас есть функция для обновления идентификатора, теперь давайте создадим файл Javscript с функцией, которая выполняет эту логику. Наш файл будет называться app.js

В этом файле у нас будет функция, которая будет вызывать код, о котором мы упоминали ранее.

[[[ТОК_6]]]

Добавление файла Javascript в Blazor

Добавьте сценарий в приложение Blazor, добавив его туда, где расположены сценарии.

[[[ТОК_7]]]

Создание сервиса

Теперь, когда у нас есть код Javascript, нам нужно создать сервис, который будет называться ThemeToggleService.

Этот сервис будет обрабатывать логику переключения между темами light и dark.

Внедрение JSInterop

Чтобы вызвать любой Javascipt, нам нужно вызвать JSInterop, поэтому нам нужно создать свойство, которое будет выполнять внедрение.

[[[ТОК_12]]]

Функция для установки идентификатора

Теперь, когда у нас есть служба, давайте создадим функцию для установки идентификатора. Эта функция будет просто обновлять data-theme на странице.

using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace BlazorDarkmodeToggle.Data
{
    public class ThemeToggleService
    {
        private readonly IJSRuntime jSRuntime;

        public ThemeToggleService(IJSRuntime jSRuntime)
        {
            this.jSRuntime = jSRuntime;
        }

        public bool IsLightTheme { get; set; } = true;
        public string GetIdentifier => IsLightTheme ? "light" : "dark";

        public async Task ToggleTheme() {
            IsLightTheme = !IsLightTheme;
            await jSRuntime.InvokeVoidAsync("toggleTheme", GetIdentifier);
        }
    }
}

Добавляем сервис в автозагрузку

Чтобы сделать сервис доступным для всех компонентов и страниц, нам необходимо добавить его в файл Program.cs.

builder.Services.AddSingleton<ThemeToggleService>();

В итоге файл будет таким

using BlazorDarkmodeToggle.Data;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddSingleton<ThemeToggleService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

Имейте в виду, что это может измениться в зависимости от того, используете ли вы Blazor Server или Blazor WebAssembly.

Запекание CSS

Теперь, когда у нас есть готовая часть кода, нам нужно начать работать над CSS. Что нам нужно сделать, так это установить все свойства CSS, которые обрабатывают цвета CSS, фон и т. д., в переменную.

:root {
    --background-color:#ffffff;
    --text-color:#000000;
}

Как только мы это сделаем, используя идентификатор, мы сможем легко переключаться между идентификаторами, и он будет использовать любое другое значение.

[data-theme="dark"] {
    --background-color: #000000;
    --text-color: #ffffff;
}

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

* {
    transition: all 250ms;
}

Теперь мы назначим эти переменные некоторым классам CSS, чтобы мы могли видеть их на странице Blazor.

.app-background {
    background-color: var(--background-color);
    width: 200px;
    height: 200px;
}

.app-text {
    color: var(--text-color);
}

Не забудьте добавить файл в приложение Blazor, добавив его в head.

<link href="css/app.css" rel="stylesheet" />

Звонок от Blazor

Итак, как мы собираемся это проверить? Для простоты мы просто добавим элемент div с классом app-background и внутри него будет p с классом app-text.Итак, давайте создадим страницу с именем Theme.razor в папке Pages и добавим для нее немного кода.

@page "/theme"
@using BlazorDarkmodeToggle.Data
@inject ThemeToggleService ThemeToggleService

<button class="btn btn-primary" @onclick=Toggle>Toggle theme</button>

<br />

<div class="app-background">
    <p class="app-text">Hello world!</p>
</div>

@code{
    public async Task Toggle()
    {
        await this.ThemeToggleService.ToggleTheme();
    }
}

Мы могли бы проверить это, перейдя в /theme, но давайте также добавим его на панель навигации.

<div class="nav-item px-3">
    <NavLink class="nav-link" href="theme">
        <span class="oi oi-list-rich" aria-hidden="true"></span> Theme togle
    </NavLink>
</div>

Тестирование

Как вы можете видеть, как только мы переключаем изменения цвета темы, фона и шрифта, теперь вы можете видеть, насколько это мощно: если вы действительно разрабатываете всю страницу, используя эти переменные в CSS, вы можете иметь разные темы и просто переключать их!

Как здорово!!

Код

Весь этот проект находится на Github, и вы можете найти его здесь!

Если у вас есть какие-либо проблемы или вопросы, не стесняйтесь обращаться ко мне в любой социальной сети по адресу @emimontesdeoca (в Твиттере на самом деле это @emimontesdeocaa с двумя aa в конце). Большую часть моих соцсетей вы также можете найти в шапке блога.

Надеюсь, вам понравился пост!

Ресурсы