假设读者已经熟悉sass,bootstrap4,vue,es6等,不然不知道我在说什么,换肤功能很常见,但哪一种方式才是最佳实践呢?下面主要分析两种常见换肤原理
第一种
传统方式,在body加一个样式(如:.theme-red
)来控制换肤,典型例子:AdminLTE
components/_tabs.scss | style.scss | theme/_theme-default.scss | theme/_theme-red.scss |
---|---|---|---|
// tab组件 @mixin tabTheme($color) { .test { color: $color; } } |
@import “components/tabs”; @import “theme/theme-default”; @import “theme/theme-red”; … |
$primary: #1890ff; body { @include tabTheme($primary); } |
$primary: #f00; .theme-red { @include tabTheme($primary); } |
要创建一种主题也很简单,照着上面的theme-red就行,我这里主要运用了@mixin和@include。可以简化,使用gulp来建(参考element-theme)
vue的话主题可以不打到style.css,比如单独的theme-red.css,在需要的页面在引入
优点:自定义性强,可以只控制某个组件
缺点:style.css会比较大,theme是固定的几个
第二种
动态插入<style>
标签,假设我们的vue项目引用了style.css(好比上面的style.scss只加入了theme-default主题)
sass里有一个方法:export{}
,类似ES6的export
,这样我们就可以在js里拿到_variables.scss里的变量
1 | // _variables.scss |
这个值可以存到$store.state.settings.themePrimary
然后在组件里的watch监听这个值有没有被改变(颜色选择器点击的时候触发改变为红色#f00),这时候有两个值:val(#f00)和oldVal(#1890ff)
改变的话,我们再去下载style.css,用正则把oldVal(#1890ff)替换为val(#f00),得到新的样式
最后创建一个style标签,把上面修改过的新样式放入style标签,然后追加到document.head,从而实现主题覆盖
优点:无需准备多套主题,可以自由动态换肤
缺点:自定义不够,只支持基础颜色的切换