为 TDesignBlazor 添加暗黑模式

news2025/1/16 6:44:54

本文将讲述我为 TDesignBlazor 开源项目提交 PR 的经历,主要介绍暗黑模式功能的实现以及之后如何在项目中使用。我将会分享我在实现这一功能时遇到的问题,以及我是如何解决这些问题的。我希望通过我的经历能够鼓励更多的人参与开源项目,为 TDesignBlazor 贡献代码,帮助项目快速迭代。

文章目录

  • 1. 背景
  • 2. 开发过程
    • 2.1 实现原理
    • 2.2 TDesignBlazor 实现思路
  • 3. 最后

1. 背景

TDesign 是腾讯各业务团队在服务业务过程中沉淀的一套企业级设计体系。其支持业界主流的 React/Vue/Angular/微信小程序/Flutter 开发技术栈,并提供桌面端和移动端两套风格统一的组件资源,是一款界面和使用体验都无可挑剔的前端框架。

TDesign 官方是没有提供 Blazor 版本的支持,很幸运的是在我自己搭好了架子捣鼓了一个组件后,发现社区已经有了一个非常完善的 TDesignBlazor。毕竟工作量非常大,一个人的力量是有限的,需要社区的力量来支撑。也是刚好看到张队转载的文章,发起者在寻求 Blazor 爱好者参与,所以我决定加入进来,帮助维护和改进这个项目。这样就能够将 TDesign 的优秀设计和交互体验带到 Blazor 项目中,提高开发效率和用户体验。我相信社区的力量,我们一起能够完成这个目标。

2. 开发过程

TDesign 组件库提供了暗色模式,并且官方的演示站点是有暗黑模式的体验。这里我们要为 TDesignBlazor 项目的演示站点添加暗黑模式,并为使用该 Blazor 组件的项目提供简单的调用暗黑模式的方式。

2.1 实现原理

根据 TDesign 文档的介绍,我们只需要给网页的 html 标签增加 theme-mode 属性即可。其组件库会自动变换颜色模式,通过此种方式也可以设置不同的颜色主题。

在这里插入图片描述

其实现的原理也非常简单,组件库使用 css variables(自定义属性)实现颜色的定义,同时定义了 :root[theme-color="custom-theme"][theme-mode="dark"] 选择器来设置浅色/暗色模式两组不同的颜色值,然后通过 js 控制 html 标签的 theme-mode 属性:setAttributeremoveAttribute 来实现主题的切换。

我们可以在官方演示站点通过 F12 打开开发人员工具,审查 html 标签来看到这些信息:

在这里插入图片描述

2.2 TDesignBlazor 实现思路

通过文档我们已经了解到,暗色模式只需要通过 js 控制 html 标签的 theme-mode 属性:

// 设置暗色模式
document.documentElement.setAttribute('theme-mode', 'dark');
// 重置为浅色模式
document.documentElement.removeAttribute('theme-mode');

这里对于 TDesignBlazor 暗黑功能的实现,我们只需要通过 .NET 调用 JavaScript 函数即可。关于这一块的相关知识可以参考微软官方文档:《JavaScript 互操作》。

参与开源项目,首先我们要遵守项目的贡献指南,更要了解这个项目。在 TDesignBlazor 项目中,src 目录下是 TDesign 的 Blazor 类库和测试项目。doc 目录下是 Blazor 类库使用的演示站点,分为 ServerSide 和 WebAssembly 两种形式,Shared 是两者共用的部分。

搞清楚了项目的基本情况,我们就可以动手添加这一部分功能了。前面我们也讲到,最好是在 Blazor 类库中提供可以直接切换的方法。

首先,在 tdesign-blazor.js 添加相关的 js 方法。

/**
 * 暗黑模式
 * */
let theme = {
    /**
     * 浅色模式
     * */
    light: function () {
        document.documentElement.removeAttribute('theme-mode');
    },
    /**
     * 暗色模式
     * */
    dark: function () {
        document.documentElement.setAttribute('theme-mode', 'dark');
    }
}

TDesignExtensions.cs 是 TDesign 的扩展,我在里面添加 ChangeThemeMode 方法。

/// <summary>
/// 执行切换暗黑和浅色模式切换
/// </summary>
/// <param name="js"></param>
/// <param name="isDark">是否为暗黑模式</param>
public static async Task ChangeThemeMode(this IJSRuntime js, bool isDark = true)
{
    var jsObject = await js.ImportScriptAsync();
    await jsObject.InvokeVoidAsync(isDark ? "theme.dark" : "theme.light");
}

对于演示站点的修改,大部分工作主要是界面上的,集中在 doc/TDesign.Docs.Shared/Layouts/MainLayout.razor。这里需要添加一个 TInputRadioGroup 主题切换的按钮,样式按照官方站点设计即可。在需要执行主题切换调用的地方执行 JS.ChangeThemeMode 方法,如下:

@using Microsoft.JSInterop
@inject IJSRuntime JS

<TInputRadioGroup @bind-Value="ThemeMode" OnValueSelected="@(e=>JS.ChangeThemeMode(e=="2"))" Size="Size.Medium" ButtonStyle="RadioButtonStyle.Outline">
    <TInputRadio Value="1">浅色</TInputRadio>
    <TInputRadio Value="2">暗黑</TInputRadio>
</TInputRadioGroup>

@code{
    int ThemeMode { get; set; } = 1;
}

3. 最后

《礼记·学记》中有这样一句:“学然后知不足,教然后知困。知不足,然后能自反也;知困,然后能自强也。故曰教学相长也。”

参与开源项目和写文章也是学习的过程,这可以让你结交不同的朋友,学到更多的知识。项目的贡献不在于大小,每个人都可以做自己力所能及的事情。要相信众人拾柴的力量,这些细小的贡献最终将有助于推动开源社区变得更好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/178488.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CE训练教程进阶,步骤 9: 注入++

目录 一、找出存放四个玩家健康值的地址 二、找出修改数据的代码 三、找出是谁调用了修改指令 四、分析玩家的内存数据 五、注入修改代码 六、C语言代码注入 相对于前面8个步骤&#xff0c;步骤9稍微要难一点&#xff0c;所以单独写。 步骤9是在步骤7的基础上&#xff0c…

Flowable进阶学习(六)网关

文章目录排他网关案例&#xff1a;并行网关案例&#xff1a;包容网关案例&#xff1a;事件网关网关(gateway)用来控制流程的流向。来实现复杂的审批流程。网关的分类包括&#xff1a;排他网关、并行网关、包容网关、事件网关。排他网关 exclusive gateway也成为异域网关XORgat…

Python数据可视化之图表组成元素

1.1绘制 matplotlib 图表组成元素的主要函数matplotlib 是如何组织内容的&#xff1f;在一个图形输出窗口中&#xff0c;底层是一个 Figure实例&#xff0c;我们通常称之为画布&#xff0c;包含一些可见和不可见的元素。在画布上&#xff0c;自然是图形&#xff0c;这些图形就是…

Allegro如何自动居中走线操作指导

Allegro如何自动居中走线操作指导 Allegro支持自动将走线居中到两个孔的中间,避免手动去调整的麻烦,类似下图 具体操作如下 点击Spread Between VoidsOptions选择需要居中走线的层面,并且Void clearance输入0

OpenGL ES着色器语言(GLSL ES)规范 ——上篇

文章目录前言OpenGL ES基础一段基本的着色器代码大小写和分号数据值类型、命名规范、类型转换运算符矢量和矩阵矢量和矩阵类型矢量构造、访问矩阵构造、访问矢量矩阵运算规则特殊类型—结构体和数组结构体数组取样器总结前言 着色器语言通过控制GPU来进行前端图形的渲染&#…

《深入浅出计算机组成原理》学习笔记 Day10

浮点数与定点数1. 浮点数的不精确性2. 定点数的表示3. 浮点数的表示参考1. 浮点数的不精确性 32 比特只能表示 2 的 32 次方个不同的数&#xff0c;差不多是 40 亿个。如果表示的数超过能表示总的个数&#xff0c;那么就会有两个不同的数的二进制表示是一样的。计算机就会不知…

【深度学习炼丹】不平衡样本的处理

目录&#xff1a;不平衡样本的处理一、前言二、数据层面处理方法2.1 数据扩充2.2 数据&#xff08;重&#xff09;采样2.3 类别平衡采样三、算法&#xff08;损失函数&#xff09;层面处理方法3.1 Focal Loss3.2 损失函数加权四、参考资料一、前言 在机器学习的经典假设中往往…

VMWare 移动Linux CentOS 7虚拟机后连不上网怎么办

研究hadoop的时候发现虚拟机太大了&#xff0c;于是把3台节点的虚拟机剪切粘贴到移动硬盘上&#xff0c;但是出现了上不了网的问题 VMWare 移动Linux CentOS 7虚拟机后连不上网&#xff0c;ifconfig命令只出现lo不出现有IP地址的ens33&#xff0c;jps命令也出现了jps command …

机器学习模型搭建与评估

模型搭建和评估第三章 模型搭建和评估--建模模型搭建任务一&#xff1a;切割训练集和测试集任务二&#xff1a;模型创建任务三&#xff1a;输出模型预测结果第三章 模型搭建和评估-评估模型评估任务一&#xff1a;交叉验证任务二&#xff1a;混淆矩阵任务三&#xff1a;ROC曲线…

python爬虫学习笔记-mysql数据库介绍下载安装

数据库概述 为什么要使用数据库&#xff1f; 那我们在没有学习数据库的时候&#xff0c;数据存放在json或者磁盘文件中不也挺好的嘛&#xff0c;为啥还要学习数据库&#xff1f; 文件中存储数据&#xff0c;无法基于文件直接对数据进行操作或者运算&#xff0c;必须借助python将…

IDEA搭建Finchley.SR2版本的SpringCloud父子基础项目-------Ribbon负载均衡

1.概念 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。简单的说&#xff0c;Ribbon是Netflix发布的开源项目&#xff0c;主要功能是提供客户端的软件负载均衡算法&#xff0c;将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配…

Python闭包与闭包陷阱

1 什么是闭包 在 Python 中&#xff0c;闭包是一种特殊的函数&#xff0c;它能够记住它所在的环境&#xff08;也称作上下文&#xff09;。这意味着闭包能够访问定义它的作用域中的变量。闭包通常用于封装数据和提供对外部访问的接口。 在 Python 中使用闭包有以下几点好处&a…

数据库和SQL概述

数据库和SQL概述 数据库的好处 实现数据的持久化使用完整的管理系统统一管理&#xff0c;易于查询 常用的一些名称缩写 DB&#xff1a;数据库(Database)&#xff1a;存储数据的“仓库”。它保存了一系列有组织的数据DBMS&#xff1a;数据库管理系统(Database Management Sy…

离线用户召回定时更新

3.6 离线用户召回定时更新 学习目标 目标 知道离线内容召回的概念知道如何进行内容召回计算存储规则应用 应用spark完成离线用户基于内容的协同过滤推荐 3.6.1 定时更新代码 完整代码 import os import sys # 如果当前代码文件运行测试需要加入修改路径&#xff0c;否则后面…

游戏启动器:LaunchBox Premium with Big Box v13.1

LaunchBox知道您会喜欢的功能&#xff0c;具有风格的游戏启动器&#xff0c;我们最初将 Launchbox 构建为 DOSBox 的一个有吸引力的前端&#xff0c;但它现在拥有对现代游戏和复古游戏模拟的支持。我们让您的所有游戏看起来都很漂亮。 整理您的游戏收藏 我们不仅漂亮&#xff…

基于微信小程序奶茶店在线点餐下单系统

奶茶在线下单系统用户端是基于微信小程序端&#xff0c;管理员端是基于web端&#xff0c;基于java编程语言&#xff0c;mysql数据库&#xff0c;idea工具开发&#xff0c;用户微信端可以注册登陆小程序&#xff0c;查看奶茶详情&#xff0c;搜索下单奶茶&#xff0c;在线奶茶评…

CSS @property(CSS 自定义属性)

CSS property&#xff08;CSS 自定义属性&#xff09;参考描述propertyHoudiniproperty兼容性描述符规则syntax扩展initial-valueinherits示例描述符的注意事项使用 JavaScript 来创建自定义属性CSS 变量与自定义属性重复赋值过渡简单的背景过渡动画更复杂的背景过渡动画错误示…

【ARM体系结构】之数据类型约定与工作模式

1、RISC和CISC的区别 1.1 RISC : 精简指令集 使用精简指令集的架构&#xff1a;ARM架构 RISC-V架构 PowerPC架构 MIPS架构ARM架构 &#xff1a;目前使用最广泛的架构&#xff0c;ARM面向的低端消费类市场RISC-V架构 &#xff1a;第五代&#xff0c;精简指令集的架构&#xff…

这样定义通用人工智能

🍿*★,*:.☆欢迎您/$:*.★* 🍿 正文 人类解决问题的途径,大体可以分为两种。一种是事实推理,另一种是事实验证。 为什么只是两种分类,因为根据和环境的交互与否。 事实推理解释为当遇到事件发生的时候,思考的过程。可以使用概率模型,或者更复杂的模型(目前没…

Out of Vocabulary处理方法

Out of Vocabulary 我们在NLP任务中一般都会有一个词表&#xff0c;这个词表一般可以使用一些大牛论文中的词表或者一些大公司的词表&#xff0c;或者是从自己的数据集中提取的词。但是无论当后续的训练还是预测&#xff0c;总有可能会出现并不包含在词表中的词&#xff0c;这…