切换主题的方案

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变量值即可,不存在优先级问题
  • 新增或修改主题方便灵活

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言刷力扣】367.有效的完全平方数

题目&#xff1a; 解题思路&#xff1a; 二分查找 时间复杂度&#xff1a; 空间复杂度&#xff1a; bool isPerfectSquare(int num) {int l 0, r 50000;while (l < r) {long long mid (l r) / 2;if (num < mid * mid) {r mid - 1;}else if (num > mid*mid) …

【番外】软件设计师中级笔记关于数据库技术更新笔记问题

提问 由于软件设计师中级笔记中第九章数据库技术基础的笔记内容太多&#xff0c;我应该分几期发布呢&#xff1f;还是一期一次性发布完成。 如果分为一期发布&#xff0c;可能需要给我多一些时间&#xff0c;由于markdown格式有所差异&#xff0c;所以我需要部分进行修改与调…

单链表的经典算法OJ

目录 1.反转链表 2.链表的中间节点 3.移除链表元素 ——————————————————————————————————————————— 正文开始 1.反转链表 typedef struct ListNode ListNode; struct ListNode* reverseList(struct ListNode* head) {//判空if(…

企业级 RAG 全链路优化关键技术

本文根据2024云栖大会实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a; 邢少敏 | 阿里云智能集团高级技术专家 活动&#xff1a; 2024 云栖大会 - AI 搜索企业级 RAG 全链路优化关键技术 在2024云栖大会上&#xff0c;阿里云 AI 搜索研发负责人之一的…

基于微博评论的自然语言处理情感分析

目录 一、项目概述 二、需要解决的问题 三、数据预处理 1、词汇表构建&#xff08;vocab_creat.py&#xff09; 2、数据集加载&#xff08;load_dataset.py&#xff09; 四、模型构建&#xff08;TextRNN.py&#xff09; 1、嵌入层&#xff08;Embedding Layer&#xff…

【Linux快速入门(三)】Linux与ROS学习之编译基础(Cmake编译)

目录 零.前置篇章 一.Cmake的由来 二.安装 三.创建并编写CMakeLists.txt 四.编译 五.优化CMakeLists.txt文件 零.前置篇章 【Linux快速入门(一)】Linux与ROS学习之编译基础&#xff08;gcc编译&#xff09;_ros linux-CSDN博客【Linux快速入门(二)】Linux与ROS学习之编译…

hadoop_hdfs详解

HDFS秒懂 HDFS定义HDFS优缺点优点缺点 HDFS组成架构NameNodeDataNodeSecondary NameNodeClient NameNode工作机制元数据的存储启动流程工作流程 Secondary NameNode工作机制checkpoint工作流程 DataNode工作机制工作流程数据完整性 文件块大小块太小的缺点块太大的缺点 文件写入…

高中数学网盘资料(每题有解析和知识点)

一、究极超能学习资源高中版 一数作为播放量过亿的哔站up实力非同一般 链接&#xff1a;https://pan.baidu.com/s/1xrcAlq6wj_LMYHcbxAKAWg 提取码&#xff1a;7MBW 复制这段内容打开「百度网盘APP 即可获取」 二、必刷题高考合订本&#xff08;刷题必备&#xff09; 链接&am…

MongoDB的基本操作

&#x1f337;数据库准备 &#x1f388;Mongoshell 1.在指定目录下创建mongodb文件夹、其子文件log和data以及mongodb.log cd /home/ubuntu mkdir -p mongodb/data mkdir -p mongodb/log touch mongodb/log/mongodb.log 执行mongodb命令启动mongdb服务 mongod --dbpath /h…

如何利用 OCR 和文档处理,快速提高供应商管理效率 ?

在当今瞬息万变的商业环境中&#xff0c;有效的供应商管理通常需要处理大量实物文档&#xff0c;这带来了巨大的挑战。手动提取供应商名称、编号和其他关键信息等关键细节非常耗时、容易出错&#xff0c;并且会降低整体效率。 为了应对这些挑战&#xff0c;组织正在逐步采用自…

ImportError: numpy.core.multiarray failed to import

ImportError: DLL load failed while importing _multiarray_umath: 找不到指定的模块。 Traceback (most recent call last): File "E:\python_code\Smart_store\test_20241021\test03.py", line 1, in <module> import cv2 File "E:\anaconda3\…

信息安全工程师(60)计算机病毒分析与防护

计算机病毒分析 介绍 计算机病毒是一种人为制造的程序&#xff0c;它通过不同的途径潜伏或寄生在存储媒体&#xff08;如磁盘、内存&#xff09;或程序里。当某种条件或时机成熟时&#xff0c;它会自生复制并传播&#xff0c;使计算机的资源受到不同程度的破坏。 定义&#xf…

7、Vue2(二) vueRouter3+axios+Vuex3

14.vue-router 3.x 路由安装的时候不是必须的&#xff0c;可以等到使用的时候再装&#xff0c;如果之前没有安装的话&#xff0c;可以再单独安装。之前的终端命令行不要关闭&#xff0c;再重新开一个&#xff0c;还需要再package.json文件的依赖中添加。 如果忘记之前是否有安…

PPT自动化:Python如何修改PPT文字和样式!

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 使用 Python 修改 PPT 文本内容📝 遍历所有幻灯片和文本框📝 设置和修改文本样式📝 复制和保留文本样式⚓️ 相关链接 ⚓️📖 介绍 📖 在日常工作中,PPT 的文字内容和样式修改似乎是一项永无止境的…

向日葵密码提取

向日葵密码提取 首先可以通过tasklist /svc来找一下程序PID 通过procdump来提取内存中的数据&#xff0c;从而从中提取密码。例如fastcode部分可以找到设备识别码&#xff0c; 临时密码会放在一个<f>标签中。 工具化 可以把工具用python语言自动化来做&#xff0c;…

SSD-Pytorch环境搭建(二)

系列文章目录 SSD-Pytorch环境搭建&#xff08;一&#xff09; SSD-Pytorch环境搭建&#xff08;二&#xff09; 文章目录 系列文章目录前言一、训练步骤1、本文使用VOC格式进行训练。2、训练前将标签文件放在VOCdevkit文件夹下的VOC2007文件夹下的Annotation中。 3、训练前将…

自己掏耳朵怎么弄干净?清洁耳朵掏耳神器推荐!

耳屎是人体的分泌物之一&#xff0c;很多人选择用传统挖耳勺或者棉签进行掏耳&#xff0c;殊不知这种行为会将耳屎越捅越深&#xff0c;甚至还会捅穿鼓膜&#xff01;那么缺少别人帮助的情况下&#xff0c;自己掏耳朵怎么弄干净呢&#xff1f;现在小编就给大家分享一款掏耳神器…

家庭事务管理系统|基于java和vue的家庭事务管理系统设计与实现(源码+数据库+文档)

家庭事务管理系统 目录 基于java和vue的家庭事务管理系统 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&#xff0c;阿里云…

React综合指南(三)

#1024程序员节&#xff5c;征文# 41、hooks的使用有什么注意事项 在使用Hooks的过程中&#xff0c;需要注意的两点是&#xff1a; 不要在循环&#xff0c;条件或嵌套函数中调用Hook&#xff0c;必须始终在React函数的顶层使用Hook。这是因为React需要利用调用顺序来正确更新…

配置nginx服务通过ip访问多网站

文章目录 第一种方法第二种方法 先关闭防火墙 # systemctl stop firewalld # setenforce 0第一种方法 #mntui 第二种方法 # vim /etc/nginx/conf.d/test_ip.conf # cat /etc/nginx/conf.d/test_ip.conf server {listen 192.168.234.100:80;#server_nameroot /test/100;loca…