🌓vue页面换肤实践__Vue.js
发布于 4 年前 作者 banyungong 1705 次浏览 来自 分享
粉丝福利 : 关注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的换肤解决方案

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: 歐企鹅 原文链接:https://juejin.im/post/6869937634714583053

回到顶部