Hooks封装前端主题

主题效果

::: block-1 在VueUse官网中有这样一个效果,就是点击切换按钮,切换页面主题,由白天切换到黑夜。 :::

今天呢我们封装一个简易前端主题Hook,主要分享其中的实现原理。

封装Hooks

准备两个主题样式

js 复制代码
export default {
    fontSize: '20px',
    Color: '#f90',
    backgroundColor: '#eee'
}
themeday.js
js 复制代码
export default {
    fontSize: '20px',
    Color: '#fff',
    backgroundColor: '#333',
}
themedark.js

新建一个hook文件夹,在hook文件夹中新建theme.ts

ts 复制代码
import { ref, type Ref } from 'vue';

// 定义你的主题类型  
interface ThemeType {
    fontSize?: string;
    Color?: string;
    backgroundColor?: string;
}

// 定义你的响应式引用类型  
type ThemedRef = Ref<ThemeType | undefined>;

// 导入你的主题对象  
import themeday from '../utils/themeday.js';
import themedark from '../utils/themedark.js';

// 初始化你的响应式引用  
let Theme: ThemedRef = ref(themeday as ThemeType);

export function useTheme() {
    let Localtheme = localStorage.getItem('theme');
    Theme.value = Localtheme ? JSON.parse(Localtheme) : themeday;

    const changeday = () => {
        Theme.value = themeday;
        localStorage.setItem('theme', JSON.stringify(themeday));
    };
    const changedark = () => {
        Theme.value = themedark;
        localStorage.setItem('theme', JSON.stringify(themedark));
    };

    // 为返回的对象添加类型注释  
    return { Theme, changeday, changedark } as { Theme: ThemedRef; changeday: () => void; changedark: () => void };
}

因为页面会刷新,所以使用localstorage把主题存入,这样切换主题后,即使页面刷新主题也不会再改变。

组件中使用

在组件中引入useTheme

html 复制代码
<template>
   <div>123123123</div>
   <button @click="changeday" style="width: 100px; height: 50px;margin-top: 100px;">明亮模式</button>
   <button @click="changedark" style="width: 100px; height: 50px;">黑暗模式</button>
</template>

<script setup lang="ts">
import { useTheme } from '@/hook/theme'
const { Theme, changeday, changedark } = useTheme()
</script>

引入成功之后该怎样修改页面样式呢?别忘了vue内置指令有一个v-bind 可以动态绑定元素,在js中可以使用,css也可以使用。

css 复制代码
<style scoped lang="scss">
div {
   width: 100px;
   height: 100px;
   border: 1px solid #ccc;
   background-color: v-bind("Theme.backgroundColor");
   font-size: v-bind("Theme.fontSize");
   color: v-bind("Theme.Color");
}
</style>

效果

谢谢观看~

相关推荐
小码哥_常11 小时前
一套自己部署的 IM,客户端是同一份 Flutter
前端·后端
蜗牛攻城狮14 小时前
微前端四大方案选型对比与最佳实践:qiankun、micro-app、wujie、Module Federation
前端·微前端·qiankun·前端架构·micro-app·wujie
她说可以呀15 小时前
Vue插槽
前端·javascript·vue.js
qq_4480111615 小时前
Vue + Jinja2两套模版与法冲突造成undefinedError
前端·javascript·vue.js
aixingpan15 小时前
aixingpan.cn API开发文档:前端查询夏令时和时区接口指南
前端·php
2601_9583529016 小时前
23.5×19mm 换掉一整条音频链?|A-68 集成了什么:ADC / DAC / 24.576MHz 时钟 / AEC / 波束降噪,主控仅需 6 根线
前端·音视频·ai降噪·回声消除·语音模块
志尊宝17 小时前
AI原生前端开发(039):AI辅助的Nuxt 4全栈开发
前端·vue.js·ai-native
FRing0318 小时前
JavaScript入门到精通三十二(深拷贝、浅拷贝、递归函数)
开发语言·前端·javascript
excel18 小时前
双 Token 与前端使用 Crypto 公私钥鉴权换 Token,哪种方案更好?
前端·后端
外收内放18 小时前
Python基础语法练习题(73)
java·前端·python