🌓vue页面换肤实践

前言

最近要做一个换肤的功能,不过只是对一个页面换肤,换一下背景图呀,背景、边框、字体颜色呀之类的,并非整个项目换肤,相对比较简单,所以以下介绍的换肤方法仅适用于页面换肤而非整个项目换肤。

方案

查阅资料后发现有两种方案

  1. 为每套皮肤写一套样式,然后最外层用一个 class 充当命名空间的功能,然后将这个 class 挂到 body 上,通过切换这个 class 达到换肤的目的
  2. 为每套皮肤写一份配置,抽出需要换肤的样式,点击换肤时,根据配置更换样式,具体请看下面代码

此处选的是方案2,因为方案1要为每套皮肤写一套样式,我觉得方案2为每套皮肤写一套配置维护起来更容易

实现

首先把需要换肤的样式抽成一个 css 文件,命名为 default-theme.css 放到 static/theme 中,作为默认主题,引入到代码中

// 假设 header 的边框色 和 footer 的背景色 和 content 的背景图片 是需要切换的
.header {
    border-color: #ffeb00;
}

.content {
    background: url("/static/theme/yellow/bg.jpg");
}

.footer {
    background-color: #ffeb00;
}
// main.js 引入默认主题
import '/static/theme/default-theme.css'

新建 theme.js 编写皮肤配置,以及用来匹配默认样式替换为关键字的 map 对象

// 主题配置
const theme = {
    yellow: {
        headerBorderColor: #ffeb00,
        contentBg: '/static/theme/yellow/bg',
        footerBgColor: #ffeb00
    },

    blue: {
        headerBorderColor: #007fff,
        contentBg: '/static/theme/blue/bg',
        footerBgColor: #007fff
    }
}

// 用 key 在默认主题中进行匹配,然后替换为 value
const themeMap = {
    '#ffeb00': 'headerBorderColor',
    '/static/theme/yellow/bg': 'contentBg',
    '#ffeb00': 'footerBgColor'
}

export { theme, themeMap }

切换主题,分四步完成

  1. 首先使用 axios 获取 default-theme.css
  2. 替换样式为关键字:用 themeMap 的 key 值去匹配,匹配上之后替换为 value
  3. 经过第2步 default-theme.css 中的样式就被替换成关键字了,这一步替换关键字为样式,用 theme 的主题的 key 去匹配,匹配上之后替换为 value
  4. 将处理过后的样式,写入到 style 上,再挂载到 document 上

还是看代码比较清晰

<template>
    <ul>
        <li @click="changeTheme('yellow')">黄色</li>
        <li @click="changeTheme('blue')">蓝色</li>
    </ul>
</template>

<script>
import { theme, themeMap } from 'theme.js'

export default {
    methods: {
        changeTheme(themeName) {
            // 第一步:获取 default-theme.css
            this.$axios.get('/static/theme/default-theme.css')
                .then(({ data }) => {
                    // 第二步:替换样式为关键字
                    Object.keys(themeMap).forEach(key => {
                      const value = themeMap[key]
                      data = data.replace(new RegExp(key, 'ig'), value)
                    })

                    // 第三步:替换关键字为样式
                    const curTheme = theme[themeName]
                    Object.keys(curTheme).forEach(key => {
                      const value = curTheme[key]
                      data = data.replace(new RegExp(key, 'ig'), value)
                    })

                    // 第四步:将处理过的样式写到 style,再挂载到 document 上
                    const styleDom = document.createElement('style')
                    styleDom.innerText = data
                    styleDom.id = 'theme-style'

                    const oldEl = document.getElementById('theme-style')
                    oldEl ? document.head.replaceChild(styleDom, oldEl) : document.head.appendChild(styleDom)
                })
        }
    }
}
</script>

参考

vue 换肤实践

基于Vue、ElementUI的换肤解决方案

原文链接:juejin.im

上一篇:在VUE 中制作 echarts 词云图
下一篇:vue中的nextTick实现原理

相关推荐

  • 🚩Vue源码——组件是如何注册的

    最近参加了很多场面试,几乎每场面试中都会问到Vue源码方面的问题。在此开一个系列的专栏,来总结一下这方面的经验,如果觉得对您有帮助的,不妨点个赞支持一下呗。 前言 在上一篇 🚩Vue源码——组件...

    23 天前
  • 🚩Vue源码——组件如何渲染成最终的DOM

    最近参加了很多场面试,几乎每场面试中都会问到Vue源码方面的问题。在此开一个系列的专栏,来总结一下这方面的经验,如果觉得对您有帮助的,不妨点个赞支持一下呗。 前言 Vue有两个核心思想,一个是数据...

    1 个月前
  • 🚩Vue源码——如何监听数据变化

    最近参加了很多场面试,几乎每场面试中都会问到Vue源码方面的问题。在此开一个系列的专栏,来总结一下这方面的经验,如果觉得对您有帮助的,不妨点个赞支持一下呗。 前言 Vue 是用数据来驱动来生成视图...

    6 天前
  • 🔥基于vue3.0.1 beta搭建仿京东淘宝的电商商城项目!

    前言 就在前段时间,vue官方发布了3.0.0-beta.1 版本,趁着五一假期有时间,就把之前的一个电商商城的项目,用最新的Composition API拿来改造一下! 👉GitHub地址请访问�...

    6 个月前
  • 🏆 掘金技术征文|双节特别篇 vue3——composition API

    vue3刚出测试版的时候尝过一次,后来学了react,才尝出点味道来,现在再尝一遍,先从重要的compositon api入手! composition api 主要是把之前vue的核心api暴露出来...

    13 天前
  • 🎉🎉🎉 一个基于vue3+vite+ts的完整项目

    VUE VBEN ADMIN2.0 介绍 vue-vben-admin-2.0 是一个全新的开源系统,基于ant-design-vue2.x,typescript4,vue3,vite实现的 ...

    10 天前
  • 🍊仿Element自定义Vue组件库

    前言 🍊 市面上目前已有各种各样的UI组件库,他们的强大毋庸置疑。但是有时候我们有必要开发一套属于自己团队的定制化组件库。还有时候原有的组件不能满足我们的各种需求,就需要在原有的组件上进行改造...

    3 个月前
  • (记录)vue、element表格首行跑到最后一行去了

    问题 项目中,我们一般会对 Element 进行二次封装,因为这样更好的全局管理组件,一处改动即可全局改动。比如你有十个表格,因为表格需要新增一个小功能(比如:右上角新增一个控制列显示的按钮),这时...

    25 天前
  • (源码分析)为什么 Vue 中 template 有且只能一个 root ?

    引言 今年,疫情并没有影响到各种面经的正常出现,可谓是络绎不绝(学不动...)。然后,在前段时间也看到一个这样的关于 Vue 的问题,为什么每个组件 template 中有且只能一个 root? 可能...

    6 个月前
  • (小白篇)vue-cli3.0创建项目+引入element-ui

    vue-cli在2018年8月份发布了3.0版本,经过重构之后,可以说是一个船心版本! 在项目都落地之后,就想升级一下cli版本,尝一尝3.0带来的舒适,也是为后面项目的开展做一个准备。

    2 年前

官方社区

扫码加入 JavaScript 社区