CSS方案实现动态更换主题和皮肤

3,592 阅读3分钟

第一天:

老板:“小刘啊,咱们网站得把这个主题色更改下,改成这个蓝色。高级大气。所有按钮啊,页面里banner横条背景啊啥的都统一一下”:

苦逼开发刘sir:“好的。老板,简单...” 于是苦逼开发刘sir进行了下面一顿操作:

使用 Less 提供的 modifyVars 即可对变量进行修改,下面是参考的 webpack 配置。

// webpack.config.js 
module.exports = { 
    rules: [ { 
        test: /\.less$/,
        use: [ // ...其他 loader 配置 
            { 
            loader: 'less-loader', 
            options: { 
            // 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。
            lessOptions: { 
                modifyVars: { 
                // 直接覆盖变量 
                'primary': '#1d7dfa', 'border-color': '#eee', 
                // 或者可以通过 less 文件覆盖(文件路径为绝对路径) 
                hack: `true; @import "your-less-file-path.less";`,
                },
              },
             }, 
           }], 
        }],
 };

第三方组件库主题色搞定。至于其他颜色。统一改成#1d7dfa呗。

第三天

老板:“小刘啊,咱们公司打算做一个sass类型的,服务不同客户。到时候不同客户这个主题色不一样,得把这个主题色改成客户那边的主题色。所有按钮啊,页面里banner横条背景啊啥的都统一一下”:

苦逼开发刘sir:“好,好,好的。。。老板..”(好家伙...内心里一万只草泥马在奔腾,sb啊,一天一改,让不让人活了...我tm...)

苦逼后端王sir:“刘sir,到时候首页我给你个接口,你拿到主题色,到时候不同企业不同主题色你自己统一,”(内心独白:好家伙。我他妈直接好家伙,还好当初没选前端,前端仔,看不掉你三百根头发.嘿嘿..)

咋噶? 刘sir陷入沉思:每次颜色都不一样,莫非动态更改这webpack的lessOptions的modifyVar??这玩意编译阶段运行,行不通啊?或者先存在本地,每个页面有需要用这个颜色的时候通过在data里引用下然后 :style="color:themeColor"? 或者通过minix来....苦逼刘sir在崩溃边缘徘徊

终于在一个月黑风高,万籁俱寂的夜晚,刘sir无意中看到了这样一个css规则: var 和:root。瞬间灵光一现:

好家伙。就它了

var()函数可以代替元素中任何属性中的值的任何部分。var()函数不能作为属性名、选择器或者其他除了属性值之外的值。(这样做通常会产生无效的语法或者一个没有关联到变量的值。

:root是一个伪类,表示文档根元素,非IE及ie8及以上浏览器都支持,在:root中声明相当于全局属性,只要当前页面引用了:root 所在文件,都可以使用var()来引用

app.vue
<template>
  <div>
  
    <router-view></router-view>
  </div>
</template>
<script>
import { getInitColor } from "../apis"

export default {
  data () {
    return {
    }
  },
  computed: {
  },
  components: { Render, Canv },
  mounted () {

  },
  methods: {
    async getThemeClor(){
        try{
           let res= await getInitColor()
           this.setThemeColor(res.data.color)
        }catch(err){
            throw new Error(err)
        }
    },
    setThemeColor (color) {
      const root = document.documentElement;
      root.style.setProperty('--theme-color', color);
      //此时我们打开控制台会发现,html节点之上的element.style 出现了一个:root--theme-color: #f90;
    },
  }
};
</script>

那具体页面中如何用呢?

------home.vue---------------
<template>
  <div>
    <h1>this is <span style="color:var(--theme-color)">home</span> page</h1>
    <button class="home-btn">homeBtn</button>
  </div>
</template>
<script>
export default {
  name: 'home',

  components: {},

  data () {
    return {

    };
  },
  created () {

  },
  mounted () {

  },
  methods: {

  }
};
</script>

<style scoped lang="less">
.home-btn {
  color: #fff;
  background: var(--theme-color);
}
</style>
------production.vue---------------
<template>
  <div>
    <h1>this is <span style="color:var(--theme-color)">production</span> page</h1>
    <button class="production-btn">homeBtn</button>
  </div>
</template>
<script>
export default {
  name: 'production',
  components: {},

  data () {
    return {

    };
  },
};
</script>

<style scoped lang="less">
.production-btn {
  color: #fff;
  background: var(--theme-color);
}
</style>

css的setProperty() 方法用于设置一个新的 CSS 属性,同时也可以修改 CSS 声明块中已存在的属性 我们给documnetElement调用setProperty(),设置一个全局的变量,--theme-color,注意写法,这里定义变量用--+变量名形式,主要是因为css中var引用的时候,只能用这种格式,这样相当于设置一个全局的变量。在具体页面中我们给需要主题色的区块添加背景色或者color的时候只需要通过 var(--theme-color),通过var就能解析--theme-color所表示的值。由于css的继承关系。这样所有页面都可以显示该主题色 关于css变量var的使用以及js操作var变量,参考阮一峰大神的文章www.ruanyifeng.com/blog/2017/0…

掉了三百根头发的苦逼前端仔刘sri得救啦