枫枫知道个人博客
首页
新闻
心情
关于
文章搜索
网站导航
项目相关
官方文档
首页
新闻
心情
关于
文章搜索
网站导航
项目相关
官方文档
登录
注册
前端主题切换
前端主题切换的原理使用最多的是以下方式 通过类名覆盖变量 用
搜索
[[ slide_text ]]
[[ item.content ]]
9
2
前端主题切换
发布时间:
2023-01-18
作者:
枫枫
来源:
枫枫知道个人博客
pinia
Vue
前端主题切换的原理使用最多的是以下方式 ## 通过类名覆盖变量 用户点击切换主题之后,给body设置class属性即可 ```CSS :root{ --bg: white; } .dark{ --bg: black; } ``` ## 主题的存储 状态存储在pinia中,持久化存储就存在localStorage中 这样做的好处就是各组件都能监听到主题的变化 ```JavaScript import {defineStore} from 'pinia' export const siteStore = defineStore('site', { state: () => { return { theme: "", }; }, actions: { // 初始化,从本地加载主题,也可以从远程加载专属用户的主题 loadTheme() { let theme = localStorage.getItem("theme") if (theme === null) { return } this.theme = theme if (theme === 'dark') { document.body.classList.add("dark") } }, // 设置主题,用户点击按钮,更新theme的值 setTheme(theme) { this.theme = theme if (theme === 'dark') { document.body.classList.add("dark") } else { document.body.classList.remove("dark") } localStorage.setItem("theme", theme) } } }) ``` ## echarts主题切换 echarts动态修改颜色比较麻烦,在官网也没找到合适的方案 可采取组件渲染的方式,重新渲染 并且,为了数据不反复获取,我们得封装两层组件 以文章日历为例 内层组件 ```JavaScript <template> <div id="calendar" style="height: 150px; width: 760px"></div> </template> <script setup> import {inject} from "vue" import {onMounted} from "vue" let echarts = inject("echarts"); // 主要 const props = defineProps({ // 主题,从父组件传递而来 theme: { type: String }, // 需要的数据,从父组件传递而来 chatData: { type: Array } }) // 白天的主题 const chatColor = { color: "#000000", inRangeColor: [ "#ebedf0", "#c6e48b", "#7bc96f", "#32af4a", "#1a792c", "#0f5e1e", "#0f491a", "#02340c" ], borderColor: "#fff", } if (props.theme === 'dark') { chatColor.color = "#5a5a5a" chatColor.inRangeColor = [ "#404148", "#c6e48b", "#7bc96f", "#32af4a", "#1a792c", "#0f5e1e", "#0f491a", "#02340c" ] chatColor.borderColor = "#222429" } async function article_calendar() { let chart = document.getElementById("calendar") if (!chart) { return } // 分成两份 let article_change = [] let article_data = [] for (const re of props.chatData) { article_data.push([ re.date, re.count ]) } article_change.push(props.chatData[0].date) article_change.push(props.chatData[props.chatData.length - 1].date) let myChart = echarts.init(chart) chatColor.option = { tooltip: { padding: 10, backgroundColor: "#555", borderColor: "#777", borderWidth: 1, formatter: function (e) { e = e.value; return '<div style="font-size: 14px; color: white">' + e[0] + ":" + e[1] + "</div>" } }, visualMap: { show: !0, showLabel: !0, categories: [0, 1, 2, 3, 4, 5, 6, 7], calculable: !0, inRange: { symbol: "rect", color: chatColor.inRangeColor }, // 对应上面的四个值 itemWidth: 12, itemHeight: 12, orient: "horizontal", left: "center", bottom: 0, textStyle: { color: chatColor.color } }, calendar: [{ top: 25, left: "center", range: article_change, // 时间范围 cellSize: [13, 13], splitLine: {show: !1}, itemStyle: { color: "#196127", borderColor: chatColor.borderColor, borderWidth: 2 }, yearLabel: {show: !1}, monthLabel: { nameMap: "ZH", fontSize: 11, color: chatColor.color }, dayLabel: { formatter: "{start} 1st", nameMap: "ZH", fontSize: 11, color: chatColor.color } }], series: [ { type: "heatmap", coordinateSystem: "calendar", calendarIndex: 0, data: article_data, } ], }; myChart.setOption(chatColor.option) window.onresize = () => { myChart.resize(); } } onMounted(() => { article_calendar() }) </script> ``` 外层组件 外层组件的作用就是监听主题的变化,控制子组件重新渲染,并且数据不需要重新获取 ```JavaScript <template> <Charts v-if="isChat" :theme="store.theme" :chat-data="dataList"></Charts> </template> <script setup> import Charts from "../components/charts.vue" import {ref, watch} from "vue"; import axios from "axios"; import {siteStore} from "../store/site_store.js"; const store = siteStore() const isChat = ref(false) const dataList = ref([]) async function loadData() { let url = "/api/calendars" let _res = await axios.get(url) let res = _res.data dataList.value.push(...res.data) isChat.value = true } loadData() // 监听theme的变化,如果变化,就控制子组件消失再显示 watch(() => store.theme, (n, o) => { if (n !== o) { isChat.value = false // 这里要一个延时才能生效 setTimeout(() => { isChat.value = true }) } }) </script> ``` 组件中使用 ```JavaScript <template> <div class="view"> <div class="theme_btn"> <button @click="setTheme('')">白色主题</button> <button @click="setTheme('dark')">黑色主题</button> </div> <div> <Charts></Charts> </div> </div> </template> <script setup> import Charts from "../components/charts_view.vue" import {ref} from "vue" import {siteStore} from "../store/site_store.js"; const theme = ref("") const store = siteStore() function setTheme(v) { store.setTheme(v) } // 加载主题 store.loadTheme() </script> ``` ## 看看效果  
9
2
上一篇:JS格式化字符串(两种方法)
下一篇:枫枫官方文档上新了!
你觉得文章怎么样
发布评论
763 人参与,0 条评论