结合scss实现黑白主题切换

是看了袁老师的视频后,自己做了一下练习。原视频地址:

b站地址https://www.bilibili.com/video/BV15z4y1N7jB/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=c6cf63302f28d94ebc02cbedcecc57ea首先创建一个全局的scss文件。我这里放在了assets文件夹中,创建了一个theme的文件夹,里面放置了一个theme.scss

css 复制代码
// 主题
$themes: (
    // 白亮
    light: (
        background: #fff,
        color: #000,
        textColor: #000
    ),
    // 暗黑
    dark: (
        background: #121212,
        color: #fff,
        textColor: #fff
    )
);

// 当前主题
$curTheme: light;

// 混合
// @mixin useTheme() {
//     html[data-theme='light'] & {
//         background-color: #fff;
//         color: #000;
//     }
//     html[data-theme='dark'] & {
//         background-color: #121212;
//         color: #fff;
//     }
// }

// 混合优化(遍历上面的主题)
@mixin useTheme() {
    @each $key, $value in $themes {
        $curTheme: $key !global; // 当前的主题
        html[data-theme = #{$key}] & { // & 表示传入什么选择器就是什么选择器
            @content; // 类似于插槽,样式可以进行传入
        }
    }
}

// 生成对应主题的变量
@function getVar($key) {
    $themeMap: map-get($themes, $curTheme);
    @return map-get($themeMap, $key);
}

然后通过vite进行这个scss文件的全局配置,这样就不用多次引入了。修改vite.config.ts文件。修改之后记得重新npm run dev,重新启动一下

javascript 复制代码
import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  // 上面的是默认的
  css: { // 引入全局的scss文件
    // css预处理器
    preprocessorOptions: {
      scss: {
        // 引入 theme.scss 这样就可以在全局中使用 theme.scss中预定义的变量和方法了
        // 给导入的路径最后加上 ; 
        additionalData: '@import "./src/assets/theme/theme.scss";'
      }
    }
  }
})

然后就可以进行测试了

javascript 复制代码
<template>
  <div class="test">
    123
  </div>

  <el-switch v-model="flag" @change="change"></el-switch>
</template>

<script setup lang="ts">
import { ref } from 'vue'

// 这里从本地取是为了保持刷新以后也能一致
const flag = ref(localStorage.getItem('theme') === 'dark' ? true : false)

const change = (flag: boolean) => {
  localStorage.setItem('theme', flag ? 'dark' : 'light') // 存本地,刷新的时候会用
  // 控制html标签,给自定义属性data-theme添加对应的值,这样对应的样式就会生效
  document.querySelector('html')?.setAttribute('data-theme', flag ? 'dark' : 'light')
}
</script>

<style lang="scss">
// 由于vite已经配置过了,所以不需要引入了。如果引入失败,那就老老实实在使用的文件中都引入
// @import '../assets/theme/theme.scss'; 

// 使用测试
.test {
  // 共有样式部分
  width: 100px;
  height: 100px;

  // 黑白主题特有部分样式
  @include useTheme() {
    background-color: getVar('background');
    color: getVar('color');
  }
}
</style>

白亮的

暗黑的

但是会有一个问题,就是刷新的时候,发现html标签的data-theme自定义属性丢失了。所以就需要在App.vue文件中,重新再给html标签设置一下data-theme自定义属性,值就是我们存本地的值

javascript 复制代码
<script setup lang="ts">
import { RouterView } from 'vue-router'

// 添加主题,每次刷新的时候还是原先选择的主题
let theme = localStorage.getItem('theme') || 'light'
document.documentElement.setAttribute('data-theme', theme)
</script>

<template>
  <RouterView />
</template>

<style lang="scss">
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

html,body,#app {
  width: 100%;
  height: 100%;
}
</style>

这样刷新的话也不会受到影响了

相关推荐
~无忧花开~2 分钟前
CSS学习笔记(五):CSS媒体查询入门指南
开发语言·前端·css·学习·媒体
程序猿小D9 分钟前
【完整源码+数据集+部署教程】【零售和消费品&存货】价格标签检测系统源码&数据集全套:改进yolo11-RFAConv
前端·yolo·计算机视觉·目标跟踪·数据集·yolo11·价格标签检测系统源码
吴鹰飞侠18 分钟前
AJAX的学习
前端·学习·ajax
JNU freshman24 分钟前
vue 技巧与易错
前端·javascript·vue.js
落一落,掉一掉31 分钟前
第十二周 waf绕过和前端加密绕过
前端
Asort32 分钟前
JavaScript设计模式(十六)——迭代器模式:优雅遍历数据的艺术
前端·javascript·设计模式
Coffeeee40 分钟前
Labubu很难买?那是因为还没有用Compose来画一个
前端·kotlin·android jetpack
我是日安41 分钟前
从零到一打造 Vue3 响应式系统 Day 28 - shallowRef、shallowReactive
前端·javascript·vue.js
开源之眼42 分钟前
深入理解 JavaScript 报错:TypeError: undefined is not a function
前端·javascript
LRH43 分钟前
时间切片 + 双工作循环 + 优先级模型:React 的并发任务管理策略
前端·react.js