我的环境
@vue/cli 4.5.8
node - v10.15.0
npm - 6.4.1
思路:
vue项目实现换肤有两部分
一、自主样式换肤
这部分换肤,在网上趴了不少贴,实现方式也是多种多样,这里不多说,看到这里来的人,肯定也看过不少贴了
说一下我的思路
考虑网上实现思路都过于复杂
有加命名空间的,有更换css文件的,有用打包工具实现的
而我都看不懂
因为只需要更改主题颜色,点缀色什么的根据项目需求,不需要实现,而且大部分点缀色都是用element-ui配色
鉴于以上考虑,我只需要拥有一个全局变量,在每次点击颜色组件,获取到颜色值后同步到标签上
思考了一下vue框架,能全局获取数据并插入dom的方式
最好是有一个全局变量
灵光一闪,实现步骤就三步:
- mixin实现不用到处定义的变量;
- vuex赋值到这个变量;
- 点击颜色组件更新vuex;
但是怎么动态更改颜色呢,如果只是改变背景色,我直接动态绑定style
但是有时候可能是边框线颜色,有时候可能是文字颜色
于是我决定做个指令,根据指令动态渲染
思路有了,上代码:
新增一个mixin.js文件
export default {
name: 'mixin',
computed: {
mTheme () {
return this.$store.state.theme;
}
}
}
在main.js引入,并注入到Vue.mixin中
import mixin from '@/mixin.js'
Vue.mixin(mixin);
到vuex顶层新增一个state属性theme
const store = new Vuex.Store({
state: {
theme: '#5E72F4'
}
})
新建一个组件theme.vue,并使用el-color-picker组件,封装成一个主题更换组件
<template>
<div class="theme">
<el-color-picker
v-model="color"
@change="handleOnColor"
size="small"
></el-color-picker>
</div>
</template>
<script>
export default {
name: 'Theme',
data () {
return {
color: ''
};
},
created() {
this.color = this.mTheme;
},
watch: {
mTheme(val) {
this.color = val;
}
},
computed: {
theme () {
return this.$store.state.theme;
}
},
methods: {
handleOnColor(value) {
this.$store.dispatch('UPDATE_THEME', value);
}
},
destroyed () {
}
}
</script>
<style lang="scss" scoped>
</style>
到man.js注册一个全局组件
import Theme from "@/components/theme.vue";
Vue.component("en-theme", Theme);
到store中添加一个 'UPDATE_THEME' 的 action
const store = new Vuex.Store({
actions: {
UPDATE_THEME({ commit }, val) {
commit('updateTheme', val)
}
}
})
创建一个theme.js文件,实现一个自定义指令
export const theme = {
bind: function (el, binding, vnode) {
setEleStyleColorAttribute(el, binding);
},
update: function (el, binding, vnode) {
setEleStyleColorAttribute(el, binding);
},
componentUpdated: function (el, binding, vnode) {
setEleStyleColorAttribute(el, binding);
}
}
function setEleStyleColorAttribute(el, binding) {
const {name, value, arg, expression, modifiers} = binding;
const {background, font, border} = modifiers;
if (background) el.style['background-color'] = value;
if (font) el.style.color = value;
if (border) el.style['border-color'] = value;
}
然后到你要绑定指令实现主题更换的地方绑定指令
<div v-theme.background="mTheme" class="img-logo" :id="'custom' + index">
{{ name.slice(0, 1) }}
</div>
二、element-ui换肤
这部分我也是在网上抄的,实现方式给大家放的链接吧。思路一模一样
最终效果
绿色箭头部分是element-ui实现换肤的地方;
紫色部分是还没有加入任何换肤处理的地方;
侧边栏和圆形图标是自定义样式实现换肤的地方
水平有限,不足之处请海涵