vue-cli3实现主题换肤功能
vue-cli3实现主题换肤功能参考自https://www.cnblogs.com/webSciprt/p/ji-yuwebpack4vuecli3xiang-mu-de-huan-fu-gong-neng.html在这位网友的代码基础上进行了些许改动并附上demo主题换肤demo 码云 https://gitee.com/hanlingsha/theme-demo实现效果主要...
vue-cli3实现主题换肤功能
参考自https://www.cnblogs.com/webSciprt/p/ji-yuwebpack4vuecli3xiang-mu-de-huan-fu-gong-neng.html
在这位网友的代码基础上进行了些许改动并附上demo
主题换肤demo 码云 https://gitee.com/hanlingsha/theme-demo
实现效果
主要依赖
style-loader vue-cli3默认采用vue-style-loader无法实现我们的需求
stylus stylus-loader 我使用了cube-ui,默认集成了stylus,大家也可以采用css或者sass
核心代码
vue.config.js (cube-ui会为我们在根目录下创建,也可以自己创建,名字必须保持一致)
chainWebpack: config => {
const stylus = config.module
.rule('stylus')
.toConfig()
const theme = {
...stylus.oneOf[3],
test: /\.styl$/
}
theme.use = [...theme.use]
theme.use[0] = {
loader: 'style-loader',
options: {
injectType: 'lazyStyleTag' // 原文中采用了useable,在我使用的过程中发生报错,查阅英文文档修正
}
}
config.module
.rule('stylus')
.merge({
oneOf: [theme]
})
}
src/common/theme.js
let obj = {}
let current = null
const theme = {
dark () {
if (!obj.dark) {
obj.dark = import('../assets/theme/theme.dark.styl')
}
return obj.dark
},
light () {
if (!obj.light) {
obj.light = import('../assets/theme/theme.light.styl')
}
return obj.light
}
}
async function setTheme (name) {
if (theme[name]) {
let style = await theme[name]()
if (current) {
current.unuse()
}
style.use()
current = style
}
}
export default setTheme
src/App.vue
<script>
import { mapMutations } from 'vuex'
import setTheme from './common/theme'
export default {
name: 'App',
methods: {
...mapMutations([
'setThemeIndex' //主要用于判断使用中的主题,设置样式,如上图中的小绿点
])
},
created () {
setTheme('light') // 默认使用浅色主题
this.setThemeIndex(1)
}
}
</script>
Theme.vue
<template>
<div class="page">
<v-header title="主题换肤"></v-header>
<div class="wrapper">
<div class="div-theme-list">
<div class="div-theme" v-for="item in themes" :key="item.index" @click="clickHandler(item.index)">
<div :class="themeColor(item.theme)">
<div v-show="item.index === theme" class="index"></div>
</div>
<div class="div-theme-title c-center-flex">深色主题</div>
</div>
</div>
</div>
<router-link tag="div" to="/" class="div-back c-center-flex">首页</router-link>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
import VHeader from '@/components/v-header'
import setTheme from '../common/theme'
export default {
name: 'Theme',
components: { VHeader },
data () {
return {
themes: [
{
index: 1,
theme: 'light',
name: '默认浅色主题'
}, {
index: 2,
theme: 'dark',
name: '深色主题'
}
]
}
},
computed: {
themeColor (theme) {
return (theme) => {
let arr = ['div-theme-color']
arr.push(theme)
return arr
}
},
...mapState([
'theme'
])
},
methods: {
clickHandler (index) {
if (index === 1) {
setTheme('light')
}
if (index === 2) {
setTheme('dark')
}
this.setThemeIndex(index) // 设置使用中的主题,于App.vue中的代码呼应
},
...mapMutations([
'setThemeIndex'
])
}
}
</script>
后面的话
对于用户和用户所选主题的绑定,采用localstorage和数据库存储都是可以的。
对于样式来说,大家可以参考我的demo,我的思路是编写公用的样式文件,然后每个主题都拥有一个自己的样式文件,引入公用文件,对颜色进行覆盖
对于可用主题的存储,我个人倾向文件存储,并导出一个数组,采用vuex或者localstorage来管理当前使用主题
注意刷新页面时,vuex会被重置
如果大家还有其他问题,可以评论
更多推荐
所有评论(0)