是看了袁老师的视频后,自己做了一下练习。原视频地址:
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
// 主题
$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,重新启动一下
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";'
}
}
}
})
然后就可以进行测试了
<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自定义属性,值就是我们存本地的值
<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>
这样刷新的话也不会受到影响了