如何利用 SCSS 实现一键换肤

article/2025/7/12 12:08:05

环境准备

首先我们需要安装 scss 解析环境

npm i sass
// 注意 sass-loader 安装需要指定版本 如果安装最新版本会报错 this.getOptions 这个方法未定义
npm i -D sass-loader@10.1.0
// 利用 normalize.css 初始化页面样式
npm i -S normalize.css

小技巧

这里讲一个小技巧,定义的时候可以先定义一个基准变量 base-param 然后其他状态的值可以依赖这个 base-param 进行缩放或放大实现。比如不同大小规模的字体可以采用这种方法。

// 行高
$line-height-base: 1.5 !default;
$line-height-lg: 2 !default;
$line-height-sm: 1.25 !default;
// ./style/settings/variable.scss// 字体颜色
$info: #17a2b8 !default;
$danger: #dc3545 !default;// 字体大小 浏览器默认 16px
$font-size-base: 1rem !default;
$font-size-lg: $font-size-base * 1.25 !default;
$font-size-slg: $font-size-base * 1.75 !default;// 字重
$font-weight-normal: 400 !default;
$font-weight-bold: 600 !default;

定义一个入口文件

// ./style/theme/index.scss@import "../settings/variable.scss";$themes-color: (default: (// 全局样式属性color: $info,font-weight: $font-weight-normal,font-size: $font-size-lg,),old: (color: $danger,font-weight: $font-weight-bold,font-size: $font-size-slg,),// ... 可自定义其他主题
);
//注意需要在./style/theme下创建对应的目录default、old
//用户vue.config.js获取目录名

vue.config.js 配置项处理

我们不想每次都引入 CSS 变量,可以在配置项中利用 CSS 插件自动注入全局变量样式。

// vue.config.jsmodule.exports = {css: {loaderOptions: {scss: {// 注意: 在 sass-loader v8 中,这个选项是 prependDataadditionalData: `@import "@/style/theme/index.scss";`,},},},
};

主题色切换

主题色定义好之后就需要对他进行切换了。这也是一键换肤最核心的逻辑。

  • 在 App.vue 文件下的 mounted 中将 body 添加一个自定义的 data-theme 属性,并将其设置为 default
// App.vue mounted() { document .getElementsByTagName("body")[0]
.setAttribute("data-theme", "default"); },
  • 利用 webpack 自定义插件遍历主题目录文件,自动生成自定义主题目录数组
// vue.config.js
const fs = require("fs");
const webpack = require("webpack");// 获取主题文件名
const themeFiles = fs.readdirSync("./src/style/theme");
let ThemesArr = [];
themeFiles.forEach(function (item, index) {let stat = fs.lstatSync("./src/style/theme/" + item);if (stat.isDirectory() === true) {ThemesArr.push(item);}
});module.exports = {css: {...},configureWebpack: (config) => {return {plugins: [// 自定义webpack插件new webpack.DefinePlugin({THEMEARR: JSON.stringify(ThemesArr),}),],};},
};
  • 切换 js 逻辑实现
    初始化页面的时候,获取到默认主题
// Home.vue
//template
<div @click="onConfirm('old')">变old</div>
<div @click="onConfirm('default')">default</div>//script
data(){return {themeValue:'',list:[''],currentTheme:'',currentThemeIndex:0}},
mounted() {this.themeValue = THEMEARR;this.currentThemeIndex = this.themeValue.findIndex((theme) => theme === "default");this.currentTheme = this.themeValue[this.currentThemeIndex];
},

把选择的主题赋值给自定义属性 data-theme

// Home.vue// 核心切换逻辑
methods: {onConfirm(currentTheme) {this.currentTheme = currentTheme;this.currentThemeIndex = this.themeValue.findIndex((theme) => theme === currentTheme);document.getElementsByTagName("body")[0].setAttribute("data-theme", THEMEARR[this.currentThemeIndex]);},
}

根vue文件下设置全局的样式

//app.vue
@import "./style/theme/index.scss";
@mixin themify() {@each $theme-name, $map in $themes-color {// & 表示父级元素  !global 表示覆盖原来的[data-theme="#{$theme-name}"] & {$theme-map: () !global;// 循环合并键值对@each $key, $value in $map {$theme-map: map-merge($theme-map,($key: $value,)) !global;}// 表示包含 下面函数 themed()@content;}}
}@function themed($key) {@return map-get($theme-map, $key);
}#app{@include themify() {color: themed("color");font-weight: themed("font-weight");font-size: themed("font-size");}
}

学习其中sass的知识

  • 使用 @each 循环
    1.循环一个 list: 类名为 icon-10px 、icon-12px、icon-14px 写他们的字体大小写法就可以如下:
    在这里插入图片描述
    2、循环一个 map:类名为 icon-primary、icon-success、icon-secondary 等,但是他们的值又都是变量,写法如下:
    在这里插入图片描述

  • map-get

map-get(map,key) 函数的作用是根据 key 参数,返回 key 在 map 中对应的 value 值。如果 key 不存在 map 中,将返回 null 值。此函数包括两个参数:

map:定义好的 map。key:需要遍历的 key。

假设要获取 facebook 键值对应的值 #3b5998,我们就可以使用 map-get() 函数来实现:
在这里插入图片描述

  • 使用&嵌套覆盖原有样式

当一个元素的样式在另一个容器中有其他指定的样式时,可以使用嵌套选择器让他们保持在同一个地方。.no-opacity &相当于.no-opacity .foo。
在这里插入图片描述

  • map-merge

合并两个 map 形成一个新的 map 类型,即将 map2 添加到 map1的尾部

$font-sizes: ("small": 12px, "normal": 18px, "large": 24px)
$font-sizes2: ("x-large": 30px, "xx-large": 36px)
map-merge($font-sizes, $font-sizes2)
结果: "small": 12px, "normal": 18px, "large": 24px,
"x-large": 30px, "xx-large": 36px
  • @content

@content 用在 mixin 里面的,当定义一个 mixin 后,并且设置了 @content;@include 的时候可以传入相应的内容到 mixin 里面
在这里插入图片描述


http://chatgpt.dhexx.cn/article/12dTCNMY.shtml

相关文章

项目实现一键换肤的功能

在publick下面分别建立两个文件 一个是默认的一个是夜间的 然后在app。vue入口文件 mounted(){let colorName localStorage.getItem(themes) || defaultlet link document.createElement(link)link.type text/csslink.relstylesheetlink.href /themes/${colorName}.cssdocu…

从零开始Vue3+Element Plus后台管理系统(17)——一键换肤的N种方案

暗黑模式 基于Element Plus和Tailwind CSS灵活的设计&#xff0c;我们很容易在项目中实现暗黑模式&#xff0c;具体可以参考之前的文章《从零开始写一个Vue3Element Plus的后台管理系统(二)——Layout页面布局的实现》 换肤方案 如果需要给用户提供更多主题&#xff0c;更丰…

三步实现Android应用内一键换肤,无需重启应用,无需编写多余代码

古人学问无遗力&#xff0c;少壮工夫老始成。 纸上得来终觉浅&#xff0c;绝知此事要躬行。 --《冬夜读书示子聿》 陆游 换肤效果演示 四种皮肤切换&#xff1a;默认白色、蓝色、绿色和玫瑰红&#xff1a; 前言 先给大家介绍一下现在比较主流的、Star比较多的换肤框架&#…

前端 “一键换肤“ 的 N 种方案

前端瓶子君&#xff0c;关注公众号 回复算法&#xff0c;加入前端编程面试算法每日一题群 前言 现在越来越多的网站都提供了拥有换肤&#xff08;切换主题&#xff09;功能&#xff0c;如 ElementUI[2]&#xff0c;既是为了迎合用户需求&#xff0c;或是为了凸显自己特点&#…

Python装逼指南——五行代码实现批量抠图

你是否曾经想将某张照片中的人物抠出来&#xff0c;然后拼接到其他图片上去&#xff0c;从而可以即使你在天涯海角&#xff0c;我也可以到此一游&#xff1f; 专业点的人使用 PhotoShop 的“魔棒”工具可以抠图&#xff0c;非专业人士可以使用各种美图 APP 来实现&#xff0c;但…

iter()函数联队*、zip()实现序列“定长”拆分——基于iterator特性拆解繁复的单行“装逼代码”,搞明白序列定长拆分“秘法”

Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅是基础那么简单…… My CSDN主页、My HOT博、My Python 学习个人备忘录好文力荐、 老齐教室 自学并不是什么神秘的东西&#xff0c;一个人一…

如何在你朋友面前装逼4(程序代码)

大家好&#xff0c;我是不讲武德。今天我来教大家在电脑上画画&#xff0c;非常简单 --------------------------------------------------------------------------------------------------------------------- 第一步&#xff1a;新建一个文本文档 第二步&#xff1a;打开…

dtree树形菜单带搜索复选框单选框插件

dtree树形菜单带搜索复选框单选框插件 用于选择部门或者选择部门下人员 效果如下图 dtree树形菜单带搜索不带单选框复选框 dtree选择部门或者选择部门下人员复选框单选框插件 带搜索 https://download.csdn.net/download/qq_27559331/9885259

OA与帆软BI跨系统用户、部门、岗位同步总结

目录 前言&#xff1a; 一、初衷 1、需要准备啥&#xff1f; 2、同步接口或者数据集 3、建立服务器数据集 代码&#xff1a; 效果&#xff1a; 二、正式同步 1、建立服务器数据集 2、建立服务器树状数据集 3、选择对应关系进行同步 4、等待与设置同步频率 5、注意事项 …

JAVA 对接钉钉API(人员、部门、官方智能工作流)20210527

前言 应公司要求&#xff0c;公司人事HR系统需要对接钉钉考勤数据&#xff0c;所以需要获取钉钉的打卡记录、出差、外出、请假、调岗的数据&#xff0c;然后转换成HR系统数据。 对接前准备 创建应用 1、首先需要管理员登录钉钉开放平台&#xff0c;创建应用。 说明 只有管理…

Element使用级联选择器

Element使用级联选择器 element的级联选择器和select不一样,下拉框我们可以手动定义label和value,只需要将查出来的值循环一下即可 但是级联选择器的视图层是这样的 只有 :options=“options” 这个属性让我们绑定值,没办法绑定他的label和value element官网给的数据结构是这…

研发部的人员素质要求及自我培养

IT行业发展已经走的很远了&#xff0c;纵观世界经济的发展&#xff0c;经济全球化进程明显加快&#xff0c;信息化已成为全球化的迫切需要和必要保证。世界范围的产业结构调整和信息技术进步&#xff0c;必将对中国信息产业的发展产生深刻影响&#xff0c;所以IT行业的前景还是…

2-Springboot集成Flowable之 选择人员的界面自定义开发

目录 效果实现思路1、新建自己的 my-assignment-popup.html2、修改properties-assignment-controller.js 效果 演示地址 代码地址 前端代码地址 实现思路 部门是基于bootstrap-treeview插件实现的&#xff0c;表格是自己用div css写的。其实自己了解angular修改这里应该没有…

用户选择框设计思路

最近新项目要用到选择人员&#xff0c;于是重新在新项目中设计了一版选人框。 效果图如下&#xff1a; 功能部分 一个选人框主要有以下几个展示部分&#xff1a; 人员组织树已选节点信息操作工具栏 这三大部分再细分下各自应有的基础功能&#xff1a; 人员展示部分&…

解读华为的流程与 IT 管理部门

公众号回复&#xff1a;干货&#xff0c;领取价值58元/套IT管理体系文档 公众号回复&#xff1a;ITIL教材&#xff0c;领取最新ITIL4中文教材 更多专业文档请访问 www.itilzj.com 华为&#xff0c;其流程与IT管理部是国内IT部门的发展标杆&#xff0c;负责的是华为各个部门和跨…

人员选择树,搜索自动筛选功能

要实现的功能截图&#xff1a; 要求&#xff1a; 1、点击收件人输入框可以根据拼音自动筛选数据&#xff0c;并且标记已经选择的数据&#xff0c;没有结果的时候提示&#xff0c;相应的更新左边树节点状态 2、勾选树右侧树的节点左侧输入框出现一一对应的节点名称 用到的…

级联选择器el-cascader处理复杂数据(四层、五层数据),回显部门以及部门下的人员

注意&#xff1a;参考第五层的数据处理比较nice 当级联选择器需要绑定的数组不再是简易数据&#xff0c;props涉及的字段不再是一个&#xff0c;而是列表里面套列表 比如&#xff0c;我想要获取部门以及下面的员工&#xff0c;如何显示&#xff1f;如下图1所示&#xff0c;后…

一个简单的联系人及组织架构选择人员的实现

前言&#xff1a;技术实现&#xff1a;Vitevue3tsvant。 本次主要是因为本人说了一个类似的功能&#xff0c;前期遇到了很多坑&#xff0c;导致 进度缓慢。虽然可以实现&#xff0c;但是都基于多个数组操作的情况&#xff0c;当涉及功能修改或优化&#xff0c;就很难实现了。 本…

jQuery仿钉钉组织架构的选择部门功能,移动端完美树形图

在网上找了好久&#xff0c;实在没见到有类似的只能自己写一个一、功能如图所示&#xff0c;点击选择无限下级功能 二、css <style>body{margin:0;padding:0;background:#ffffff}.spaceBetween {display: flex;justify-content: space-between;align-items: center;}.su…