foreword
When switching, do not re-adjust the interface
Implementation
1. First create a js file that stores public css variables
Store the css variables that need to be defined in the js file, for example (variable.js)
2. Use these css variables on the page
3. Install css-vars-ponyfill
the plugin
npm i css-vars-ponyfill
" css-vars-ponyfill
" Official concept: a ponyfill that provides client-side support for CSS custom properties (aka "CSS variables") in legacy and modern browsers. (For specific usage and concepts, please refer to the official website)
4. Encapsulate the js that switches the theme, and make an initialization call in main.js
theme.js
// theme.js
import {
lightTheme, darkTheme } from "@/assets/js/variable"
import cssVars from "css-vars-ponyfill"
export const initTheme = (theme) => {
document.documentElement.setAttribute("data-theme", theme ? "dark" : "light")
cssVars({
watch: true, // 当添加,删除或修改其<link>或<style>元素的禁用或href属性时,ponyfill将自行调用
variables: theme ? darkTheme : lightTheme, // variables 自定义属性名/值对的集合
onlyLegacy: false, // false 默认将css变量编译为浏览器识别的css样式 true 当浏览器不支持css变量的时候将css变量编译为识别的css
})
}
5. main.js call
import {
initTheme } from './theme'
let theme = localStorage.getItem('theme') === 'light' ? false : true
initTheme(theme)
6. Home.vue switch theme (I have pictures in the folder here)
<template>
<div class="home">
<div>
<el-switch
v-model="theme"
@change="changeSkin"
active-text="黑色背景"
inactive-text="白色背景"
>
</el-switch>
</div>
<div class="box">
<div class="left"></div>
<div class="right"></div>
</div>
<div class="less_box add">
<img :src="avatar" alt="" />
<el-input v-model="input" placeholder="请输入内容"></el-input>
</div>
</div>
</template>
<script>
import {
initTheme } from '@/theme'
import {
mapState, mapMutations } from 'vuex'
// import BUS from '@/utils/bus'
export default {
data () {
return {
theme: true,
input: ''
}
},
computed: {
...mapState({
sysTheme: 'theme' }),
avatar () {
// let theme = this.sysTheme === false ? 'light' : 'dark'
return require(`@/assets/images/logo-${
this.sysTheme}.png`)
}
},
watch: {
},
mounted () {
console.log(this.sysTheme);
this.theme = this.sysTheme === 'dark' ? true : false
// document.body.style.setProperty('--bottom-bg', '#0094ff');
// initTheme(this.theme)
// console.log(1111);
},
methods: {
...mapMutations({
setTheme: 'setTheme'
}),
changeSkin () {
localStorage.setItem('theme', this.theme ? 'dark' : 'light')
this.setTheme(this.theme ? 'dark' : 'light')
initTheme(this.theme)
},
// setThemeValue (theme) {
// theme = theme ? "light" : "dark";
// this.avatar = require(`@/assets/images/logo-${theme}.png`);
// }
}
}
</script>
<style lang="less" scoped>
.home {
.box {
margin-top: 100px;
display: flex;
justify-content: center;
align-items: center;
.left {
background-color: var(--left-bg);
height: 500px;
flex: 1;
}
.right {
background-color: var(--right-bg);
height: 500px;
flex: 1;
}
}
.less_box {
height: 200px;
width: 1500px;
display: flex;
}
}
</style>
7. Use in app.vue
8. vuex persistence
import Vue from "vue";
import Vuex from "vuex";
// import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
theme: localStorage.getItem('theme') === 'light' ? 'light' : 'dark'
},
mutations: {
setTheme (state, data) {
state.theme = data
}
},
actions: {
},
modules: {
},
// plugins: [
// createPersistedState({
// storage: window.localStorage,
// reducer (val) {
// // console.log(val);
// return val
// }
// })]
});
So far, all the color switching and picture switching have been completed. Let me talk about the idea of picture switching: the path of the picture is mainly obtained by using computed, so when we change the theme, the theme value saved by vuex will change, and the computed This change will be monitored to achieve the effect of replacing the image path.