热搜:fiddler git ip ios 代理
历史搜索

前端 Vue一键换肤 的方法总结

游客2024-11-02 12:03:02
目录文章目录
  1. 一、CSS 样式覆盖实现
  2. 二、实现多套 CSS 主题样式
  3. 三、CSS 变量实现
  4. 核心
  5. 四、主题图片切换
  6. 结语

现在越来越多的网站都提供了拥有换肤(切换主题)功能,如 elementui,既是为了迎合用户需求,或是为了凸显自己特点,因此提供了个性化定制的功能.

其实之前就想了解和实现 “一键换肤” 功能,但是由于种种原因一直拖到了现在。

一、CSS 样式覆盖实现

核心

通过切换 css 选择器的方式实现主题样式的切换.

  • 组件中保留不变的样式,将需要变化的样式进行抽离
  • 提供多种样式,给不同的主题定义一个对应的 CSS 选择器
  • 根据不同主题设置不同的样式

实现

下面通过 vuex 存储和控制全局的主题色,其代码如下:

import { createStore } from 'vuex'

// 创建一个新的 store 实例
const store = createStore({
  state () {
    return {
      theme: 'light'
    }
  },
  mutations: {
    setTheme (state, payload) {
      state.theme = payload
      document.querySelector('body').className = payload
    }
  }
})

export default store

在 template 模板中通过 vuex 中的主题设置对应类名,如头部代码如下:

<template>
  <div :>
    <span>{{title}}</span>
    <input v-model="checked" type="checkbox"  @change="changeTheme" />
  </div>
</template>

下面 theme.css 中通过 .light 和 .dark 两个类选择器来区分明亮主题和暗黑主题,并且事先准备了它们对应的样式,如下:

/* light 默认主题*/
body.light {
  background-color: #fff;
}

.header.light {
  background-color: #fff;
  border-bottom: 1px solid #d6d6d6;
  color: rgb(51, 50, 50);
}

.list.light .title {
  color: rgb(51, 50, 50);
}
.list.light .describe{
  color: rgb(158, 158, 158);
}

.list.light .left{
  border: 1px solid rgb(51, 50, 50);
}

/* dark 暗黑主题 */
body.dark {
  background-color: rgb(51, 50, 50);
}

.header.dark {
  background-color: rgb(51, 50, 50);
  border-bottom: 1px solid #fff;
  color: #fff;
}

.list.dark .title {
  color: #fff;
}
.list.dark .describe{
  color: rgb(201, 201, 201);
}
.list.dark .left{
  border: 1px solid #fff;
  background-color: #fff;
}

缺点

  • 多种主题样式都要引入,导致代码量增大
  • 样式不易管理
  • 查找样式复杂
  • 开发效率低
  • 拓展性差

二、实现多套 CSS 主题样式

核心

实现多套 CSS 主题样式,根据用户切换操作,通过 link 标签动态加载不同的主题样式,主要解决了多个主题色被编译到一个文件中导致单个文件过大。

实现

css 部分直接拆分成 ligth.css 和 dark.css 两个文件。

设置主题部分的 setTheme.js 代码如下:

export default function setTheme(theme = 'ligth') {
  let link = document.querySelector('#theme-link')
  let href = "/theme/" + theme + ".css"
  
  if (!link) {
    let head = document.querySelector('head')
    link = document.createElement('link')
    link.id = '#theme-link'
    link.rel = "stylesheet"
    link.href = href
    head.appendChild(link)
  } else {
    link.href = href
  }
}

缺点

  • 需要重复 CV 多份样式文件进行单独修改
  • 没有单独提取出可变的样式部分
  • 需要提前知道打包后的文件路径,否则可能导致主题样式引入错误

三、CSS 变量实现

核心

通过 body.style.setProperty(key, value) 动态修改 body 上的 CSS 变量,使得页面上的其他部分可以应用最新的 CSS 变量对应的样式。

前端 Vue一键换肤 的方法总结 1

结语

以上就是目前了解到一些的换肤方案,以上全部基于 css 去实现的,不过知道了原理就可以结合 less 和 sass 进行更好的实现。

参考文章:点击这里

标签:CSS