学习主题切换功能
根据 Vant 源码学习 模仿实现主题切换功能
实现思路
- 需要
var()变量控制 - 存放
theme是light还是dark light、dark分别有两种不同 颜色变量提供- 切换的时候 添加
class和 移除class
主要思路就是这么多 接下来 看一下var()变量需要哪些
vars.scss 文件:
这部分是之前搬了vant的变量来用,改了一下名字
:root {
// colors
--tsl-blck:#000;
--tsl-white:#fff;
--tsl-gray-1:#f7f8fa;
--tsl-gray-2:#f2f3f5;
--tsl-gray-3:#ebedf0;
--tsl-gray-4:#dcdee0;
--tsl-gray-5:#c8c9cc;
--tsl-gray-6:#969799;
--tsl-gray-7:#646566;
--tsl-blue:#1989fa;
--tsl-green:#33c88e;
// sizes
--tsl-padding: 24px;
--tsl-row-max-width: 1680px;
--tsl-nav-width: 220px;
--tsl-border-radius: 20px;
--tsl-simulator-width: 360px;
--tsl-simulator-height: 620px;
--tsl-header-top-height: 64px;
}
.tsl-theme-light {
// text
--tsl-text-color-1: var(--tsl-black);
--tsl-text-color-2: var(--tsl-gray-8);
--tsl-text-color-3: #34495e;
--tsl-text-color-4: var(--tsl-gray-6);
--tsl-link-color: var(--tsl-blue);
// background
--tsl-background: #eff2f5;
--tsl-background-2: var(--tsl-white);
--tsl-background-3: var(--tsl-white);
--tsl-header-background: #011f3c;
--tsl-border-color: var(--tsl-gray-2);
// code
--tsl-code-color: #58727e;
--tsl-code-comment-color: var(--tsl-gray-6);
--tsl-code-background: var(--tsl-gray-1);
// blockquote
--tsl-blockquote-color: #2f85da;
--tsl-blockquote-background: #ecf9ff;
}
.tsl-theme-dark {
// text
--tsl-text-color-1: var(--tsl-white);
--tsl-text-color-2: rgba(255, 255, 255, 0.9);
--tsl-text-color-3: rgba(255, 255, 255, 0.75);
--tsl-text-color-4: rgba(255, 255, 255, 0.6);
--tsl-link-color: #1bb5fe;
// background
--tsl-background: #202124;
--tsl-background-2: rgba(255, 255, 255, 0.06);
--tsl-background-3: rgba(255, 255, 255, 0.1);
--tsl-header-background: rgba(1, 31, 60, 0.3);
--tsl-border-color: #3a3a3c;
// code
--tsl-code-color: rgba(200, 200, 200, 0.85);
--tsl-code-comment-color: var(--tsl-gray-7);
--tsl-code-background: rgba(0, 0, 0, 0.24);
// blockquote
--tsl-blockquote-color: #bae6fd;
--tsl-blockquote-background: rgba(7, 89, 133, 0.25);
}
其实还是清晰可见,分成三个部分
- :root
- light
- dark
其中 light 和 dark 两个类名 下面分别包含了不同的颜色值 都是基于root的色调,那么这就导致我切换到light 或者是dark 的时候,对应的颜色值也就发生了改变
注:没有使用过var()的话 可以去这里css var 函数
根据上面这句话很重要 接下来我们就需要写逻辑 来触发切换了,我使用的是 pnpm+vite+vue3+ts+scss 构建的一个简单项目
##
pnpm create vite 手动选择 ts+vue
pnpm i 安装依赖包
pnpm i sass sass-loader -D 下载sass
pnpm dev 启动服务
把上面的变量存放在我们的style/vars.scss 的文件下 在引入到main.ts
剩余部分 我就统一放在App.vue 文件中了 下面就是我的结构
<template>
<div class="wrapper">
<ul class="nav">
<li>
<img class="link" @click="toggleTheme" :src="themeImg()" alt="" />
</li>
</ul>
<div class="content">
<button class="btn">按钮</button>
<div>123</div>
</div>
</div>
</template>
<script lang="ts">
import { ref, watch } from 'vue';
import { getDefaultTheme, useCurrentTheme } from './utils/theme';
export default {
name: '',
setup() {
const currentTheme = ref<string>(getDefaultTheme());
const theme = useCurrentTheme();
watch(
currentTheme,
(newVal, oldVal) => {
window.localStorage.setItem('tslTheme', newVal);
document.documentElement.classList.remove(`tsl-theme-${oldVal}`);
document.documentElement.classList.add(`tsl-theme-${newVal}`);
},
{
immediate: true,
}
);
watch(
theme,
(newVal, oldVal) => {
document.documentElement.classList.remove(`tsl-theme-${oldVal}`);
document.documentElement.classList.add(`tsl-theme-${newVal}`);
},
{
immediate: true,
}
);
const themeImg = () => {
if (currentTheme.value === 'light') {
return 'https://b.yzcdn.cn/vant/dark-theme.svg';
} else {
return 'https://b.yzcdn.cn/vant/light-theme.svg';
}
};
const toggleTheme = () => {
currentTheme.value = currentTheme.value === 'light' ? 'dark' : 'light';
};
return {
currentTheme,
themeImg,
toggleTheme,
};
},
};
</script>
<style lang="scss">
.w {
width: 1200px;
}
.tsl-theme-light {
background-color: var(--tsl-gray-1);
}
.tsl-theme-dark {
background-color: var(--van-doc-black);
}
.wrapper {
width: 100vw;
height: 100vh;
background: var(--tsl-background);
.nav {
width: 100%;
height: 92px;
background-color: var(--tsl-border-color);
.link {
width: 40px;
height: 40px;
.img {
display: block;
width: 40px;
height: 40px;
object-fit: cover;
}
}
}
.btn {
width: 60px;
height: 38px;
color: var(--tsl-text-color-1);
background-color: var(--tsl-background-2);
}
div {
color: var(--tsl-text-color-1);
}
}
</style>
getDefaultTheme功能: 从localStorage中读取theme 没有就默认light
useCurrentTheme功能:调用 getDefaultTheme 函数返回一个theme
接着看 toggleTheme 函数 很简单 就是赋值 dark 和 light
主要就是监听 currentTheme 给html 上绑定一个类名 theme-light 和 theme-dark
类名切换以后 颜色变量赋值不同 就导致样式颜色切换
最终就实现了主题切换的效果