切换主题的方案

1、link标签动态引入

其做法就是提前准备好几套CSS主题样式文件,在需要的时候,创建link标签动态加载到head标签中,或者是动态改变link标签的href属性

优点:实现了按需加载,提高了首屏加载时的性能
缺点:

  • 动态加载样式文件,如果文件过大网络情况不佳的情况下可能会有加载延迟,导致样式切换不流畅
  • 如果主题样式表内定义不当,也会有优先级问题
  • 各个主题样式是写死的,后续针对某一主题样式表修改或者新增主题也很麻烦

2、提前引入所有主题样式,做类名切换

不同的样式定义不同的类名,切换主题,修改对应的类名即可

/* day样式主题 */
body.day .box {color: #f90;background: #fff;
}
/* dark样式主题 */
body.dark .box {color: #eee;background: #333;
}

优点:不用重新加载样式文件,在样式切换时不会有卡顿
缺点:

  • 首屏加载时会牺牲一些时间加载样式资源
  • 如果主题样式表内定义不当,也会有优先级问题
  • 各个主题样式是写死的,后续针对某一主题样式表修改或者新增主题也很麻烦

3、 CSS变量+类名切换

首先把所有的样式文件在初始化的时候就加载进来,切换时候将指定的根元素类名进行切换,默认在根做作用域下定义好CSS变量,只需在不同的主题下更改CSS变量对应的取值即可
实现方案如下:

:root {--theme-color: red;--theme-background: #eee;
}
.pink{--theme-color: yellow;--theme-background: pink;
}
.box{color: var(--theme-color);
}

优点:

  • 不用重新加载样式文件,在样式切换时不会有卡顿
  • 在需要切换主题的地方利用var()绑定变量即可,不存在优先级问题
  • 新增或修改主题方便灵活,仅需新增或修改CSS变量即可,在var()绑定样式变量的地方就会自动更换

缺点:首屏加载时会牺牲一些时间加载样式资源

4、Vue3新特性(v-bind)

简单用法:

<script setup>// 这里可以是原始对象值,也可以是ref()或reactive()包裹的值,根据具体需求而定const theme = {color: 'red'}
</script><template>
<p>hello</p>
</template><style scoped>p {color: v-bind('theme.color');}
</style>

Vue3中在style样式通过v-bind()绑定变量的原理其实就是给元素绑定CSS变量,在绑定的数据更新时调用CSSStyleDeclaration.setProperty更新CSS变量值

实现思考:
前面方案3基于CSS变量绑定样式是在:root上定义变量,然后在各个地方都可以获取到根元素上定义的变量。现在的方案我们需要考虑的问题是,如果是基于JS层面如何在各个组件上优雅地使用统一的样式变量?

我们可以利用Vuex或Pinia对全局样式变量做统一管理,如果不想使用类似的插件也可以自行封装一个hook,大致如下:

// 定义暗黑主题变量
export default {fontSize: '16px',fontColor: '#eee',background: '#333',
};// 定义白天主题变量
export default {fontSize: '20px',fontColor: '#f90',background: '#eee',
};import { shallowRef } from 'vue';
// 引入主题
import theme_day from './theme_day';
import theme_dark from './theme_dark';// 定义在全局的样式变量
const theme = shallowRef({});export function useTheme() {// 尝试从本地读取const localTheme = localStorage.getItem('theme');theme.value = localTheme ? JSON.parse(localTheme) : theme_day;const setDayTheme = () => {theme.value = theme_day;};const setDarkTheme = () => {theme.value = theme_dark;};return {theme,setDayTheme,setDarkTheme,};
}

使用自己封装的主题hook

<script setup lang="ts">
import { useTheme } from './useTheme.ts';
import MyButton from './components/MyButton.vue';const { theme } = useTheme();
</script><template><div class="box"><span>Hello</span></div><my-button />
</template><style lang="scss">
.box {width: 100px;height: 100px;background: v-bind('theme.background');color: v-bind('theme.fontColor');font-size: v-bind('theme.fontSize');
}
</style><script setup lang="ts">
import { useTheme } from '../useTheme.ts';const { theme, setDarkTheme, setDayTheme } = useTheme();const change1 = () => {setDarkTheme();
};const change2 = () => {setDayTheme();
};
</script><template><button class="my-btn" @click="change1">dark</button><button class="my-btn" @click="change2">day</button>
</template><style scoped lang="scss">
.my-btn {color: v-bind('theme.fontColor');background: v-bind('theme.background');
}
</style>

优点:

  • 不用重新加载样式文件,在样式切换时不会有卡顿
  • 在需要切换主题的地方利用v-bind绑定变量即可,不存在优先级问题
  • 新增或修改主题方便灵活,仅需新增或修改JS变量即可,在v-bind()绑定样式变量的地方就会自动更换

缺点:

  • 首屏加载时会牺牲一些时间加载样式资源
  • 这种方式只要是在组件上绑定了动态样式的地方都会有对应的编译成哈希化的CSS变量,而不像方案3统一地就在:root上设置(不确定在达到一定量级以后的性能),也可能正是如此,Vue官方也并未采用此方式做全站的主题切换

5、SCSS+mixin+类名切换

SCSS的混合+CSS类名切换,主要是将使用到mixin混合的地方编译为固定的CSS以后,再通过类名切换去做样式的覆盖

// 定义scss变量
/* 背景颜色规范(主要) */
$background-color-theme: #d43c33;
$background-color-theme1: #42b983;
$background-color-theme2: #333;// 定义混合mixin
@mixin bg_color(){background: $background-color-theme;[data-theme=theme1] & {background: $background-color-theme1;}[data-theme=theme2] & {background: $background-color-theme2;}
}// 设置对应的主题
test2(){document.documentElement.setAttribute('data-theme', 'theme1')
}// 需要展示样式的地方
.test{@include bg_color()
}

优点:

  • 不用重新加载样式文件,在样式切换时不会有卡顿
  • 在需要切换主题的地方利用mixin混合绑定变量即可,不存在优先级问题
  • 新增或修改主题方便灵活,仅需新增或修改SCSS变量即可,经过编译后会将所有主题全部编译出来

缺点:首屏加载时会牺牲一些时间加载样式资源

6、CSS变量+动态setProperty

这种方案多用于颜色不确定时用,前面几种适用于颜色确定的时的方案

// 首先定义默认样式
:root {--theme-color: pink;--theme-background: #eee;
}// 封装改变样式的方法
const setCssVar = (prop, val, dom = document.documentElement) => {dom.style.setProperty(prop, val)
}
export default setCssVar//调用方法
import setCssVar from '@/utils/test'
test2(){console.log(setCssVar)setCssVar('--theme-color', 'red')
}// 应用主题色的样式
.test{color: var(--theme-color);
}

优点:

  • 不用重新加载样式文件,在样式切换时不会有卡顿
  • 仔细琢磨可以发现其原理跟方案4利用Vue3的新特性v-bind是一致的,只不过此方案只在:root上动态更改CSS变量而Vue3中会将CSS变量绑定到任何依赖该变量的节点上。
  • 需要切换主题的地方只用在:root上动态更改CSS变量值即可,不存在优先级问题
  • 新增或修改主题方便灵活

缺点:首屏加载时会牺牲一些时间加载样式资源(相对于前几种预设好的主题,这种方式的样式定义在首屏加载基本可以忽略不计)

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

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

相关文章

VTK的学习方法-第二类型应用

VTK的高级使用方法是自己写一个算法&#xff08;Filter&#xff09;&#xff0c;本文使用的数据类型位polydata&#xff0c;这个数据类型应用比较广泛。 我们的算法一般是继承VTK里面的vtkpolydataalgorithm&#xff0c;然后自己添加一些变量&#xff0c;重写&#xff08;over…

在Ubuntu 20.04 上安装 CoppeliaSim

在 Ubuntu 20.04 上安装 CoppeliaSim Edu V4.6.0 rev18 的步骤如下&#xff1a; 1. 下载安装文件: 首先&#xff0c;确保您已经下载了 CoppeliaSim_Edu_V4_6_0_rev18_Ubuntu20_04.tar.xz 文件。您可以从 Coppelia Robotics 的官方网站下载。 2. 解压缩文件: 打开终端&#…

关于Oracle透明数据加密(TDE)的两个概念

在上一篇文章“Oracle TDE和表空间中的数据量有关系吗&#xff1f;”中&#xff0c;我们证明了加密和解密的时间和表空间内是否有数据没有关系。 本文论证&#xff1a;加密和解密的时间基本相等&#xff0c;如果是Exadata&#xff0c;解密会稍快&#xff0c;因为Exadata支持解…

开发面试题-更新中...

探迹科技&#xff08;腾讯面试官&#xff09; 1.了不了解循环屏障 2.对于java中的线程冲突有多少了解&#xff08;我要算1加到1亿&#xff09; 3.mysql调优怎么调&#xff08;我跟他讲了explain&#xff09; 4.type中ref&#xff0c;range,const的区别 5.我有1亿的数据量&…

京东 北京 java 中级: 哪些情况下的对象会被垃圾回收机制处理掉? 哪些对象可以被看做是 GC Roots 呢?对象不可达,一定会被垃圾收集器回收么?

我同学最近在面试java的岗位, 这是他遇到的某些关于java的JVM中垃圾回收相关的部分的问题, 他来问我, 我特以此文章来解答. 公司 京东 base 北京 面试时间 2024年10月23日16:00:00 他跟我说, 面试官一上来就问了一个关于JVM的问题, 直接就给他难住了, 问题是 : 哪些情况下…

深入理解Qt中的QTableView、Model与Delegate机制

文章目录 显示效果QTableViewModel(模型)Delegate(委托)ITEM控件主函数调用项目下载在Qt中,视图(View)、模型(Model)和委托(Delegate)机制是一种非常强大的架构,它们实现了MVC(模型-视图-控制器)设计模式。这种架构分离了数据存储(模型)、数据展示(视图)和数据操作(委托),使…

通过Python爬虫获取商品销量数据,轻松掌握市场动态

为什么选择Python爬虫&#xff1f; 简洁易用&#xff1a;Python语言具有简洁的语法和丰富的库&#xff0c;使得编写爬虫变得简单高效。强大的库支持&#xff1a;Python拥有强大的爬虫框架&#xff08;如Scrapy、BeautifulSoup、Requests等&#xff09;&#xff0c;可以快速实现…

【记录】Django数据库的基础操作

数据库连接 在Django中使用 mysqlclient 这个包用于数据库的连接&#xff0c;切换至 Django环境中直接 pip install mysqlclient 安装此包 1 数据库连接配置 在项目目录下的setting.py中配置 DATABASES {default: {ENGINE: django.db.backends.mysql,NAME: mini,#数据库名US…

Tips--解决更新resource.qrc之后新的资源无法加载的问题

解决更新resource.qrc之后新的资源无法加载的问题 问题原因解决方法 问题 在使用pyQT或者pyside开发桌面程序的时候&#xff0c;resource.qrc是整合资源文件的地方&#xff0c;如下所示 <!DOCTYPE RCC><RCC version"1.0"> <qresource><file&g…

uniapp修改input中placeholder样式

Uniapp官方提供了两种修改的属性方法&#xff0c;但经过测试&#xff0c;只有 placeholder-class 属性能够生效 <input placeholder"请输入手机验证码" placeholder-class"input-placeholder"/><!-- css --> <style lang"scss" s…

Vue--绑定class样式

有三种方式&#xff1a; 1、字符串写法(freeA) 适用于&#xff1a;样式的类名不确定&#xff0c;需要动态指定 2、数组写法(freeB) 适用于&#xff1a;要绑定的样式个数不确定&#xff0c;名字也不确定 3、对象写法(freeC) 适用于&#xff1a;要绑定的样式个数确定&#xff0c…

Python的买家秀大揭秘:用代码点亮API数据

在一个充满无限可能的数字世界里&#xff0c;Python侦探正准备开始他的新任务&#xff1a;揭开买家秀API数据的神秘面纱。这不仅是一次技术的挑战&#xff0c;更是一次与时间赛跑的较量。Python侦探&#xff0c;这位编程界的福尔摩斯&#xff0c;打开了他的笔记本电脑&#xff…

sealed class-kotlin中的封闭类

在 Kotlin 中&#xff0c;sealed class&#xff08;密封类&#xff09;是一种特殊的类&#xff0c;用于限制继承的类的数量。密封类可以被用来表示一组有限的类型&#xff0c;通常用于状态管理或表达多种可能的错误类型。 密封类用 sealed 关键字定义&#xff0c;这意味着只能…

matlab怎样自动搜索文件夹中的所有txt文件,并将每个txt文件中的数据存放到一个cell数组中——MATLAB批量处理数据

在使用MATLAB批量处理数据时&#xff0c;有时候需要自动搜索文件夹中的所有txt文件&#xff0c;并将每个txt文件中的数据存放到一个以一定规律命名的变量中&#xff0c;以便于后续通过循环处理每个变量数据。 然而&#xff0c;MATLAB并不支持在变量名中直接使用i来动态生成变量…

Unity发送Http

本篇实现在Unity中发送Http请求。 讲解Get&#xff0c;Post&#xff0c;用于在Unity中进行数据对接。 一、Get IEnumerator Get() {string url "";//链接UnityWebRequest request UnityWebRequest.Get(url);//创建UnityWebRequest实例并设置请求方式为Getyield …

Flutter 中的 PopScope 小部件:全面指南

Flutter 中的 PopScope 小部件&#xff1a;全面指南 在 Flutter 应用开发中&#xff0c;导航和路由管理是构建复杂应用时必须面对的挑战之一。PopScope 小部件是 Flutter 2.0 版本引入的一个新功能&#xff0c;它提供了一种更灵活的方式来控制页面的弹出和返回行为。本文将带你…

OpenCV高级图形用户界面(9)更改指定窗口的位置函数moveWindow()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 将窗口移动到指定的位置。 cv::moveWindow() 函数用于更改指定窗口的位置。你可以使用这个函数来移动窗口到屏幕上的任何位置。 函数原型 void …

C++大坑之——多继承(菱形继承)

文章目录 前言一、多继承是什么&#xff1f;1. 多继承概念2. 多继承语法 二、菱形继承1. 为什么会有菱形继承问题&#xff1f;2. 代码感受菱形继承3. 虚拟继承1&#xff09;虚拟继承概念及语法2&#xff09;虚拟继承的原理 4. 为什么要有虚基表&#xff1f;5. 为什么要有偏移量…

bootloader跳转app卡死(IAP卡死)

1、 关闭所有中断再跳转APP 一般bootloader跳转到APP时要关闭app中用到的中断(防止中断打断程序的运行&#xff0c;导致程序跑飞&#xff09;&#xff0c;那么查看系统中用到的中断&#xff1a;串口中断、滴答定时器中断&#xff0c;所以&#xff0c;跳转之前要关闭这两个中断&…

Vlan和Trunk

VLAN的定义 虚拟局域网&#xff0c;用来在二层网络中隔离广播域不同VLAN的设备在二层网络中无法互相通讯&#xff08;二层隔离技术&#xff09; VLAN的转发过程举例 源MAC字段后加上VLAN TAG字段&#xff0c;其中VLAN ID用来标识VLAN。 PC发送数据帧进入交换机&#xff0c;会…