详解Vue 换肤方案验证


Posted in Javascript onAugust 28, 2019

本文的换肤方案灵感来自于 element-ui

需求:网站换肤,主题切换。网站的主题色可以在几种常用颜色之间进行切换,还有相关图片、图标也要跟随主题进行切换。

不多说,先看下最终的实现效果:

详解Vue 换肤方案验证

文章由两部分组成:css切换,图片图标切换

css切换

1.在 static 目录下新建一个 styles 文件夹,在 styles 下新建一个 theme.scss 文件(项目使用了sass,会自动编译成css文件,如果没有使用这些预处理工具可以直接新建 theme.css),将需要替换的 CSS 声明在此文件中。

.theme-test-btn {
  background-color: #409eff;
  border-color: #409eff;
}

.theme-test-btn:hover,
.theme-test-btn:focus {
  background-color: #66b1ff;
  border-color: #66b1ff;
}

2.在 src/assets/js/const/ 目录下新建 theme-colors.js,用于声明所有可选的主题,每种颜色都对应一个关键词,方便区分

const colors = [
  {
    themeId: 0,
    primaryBtn: '#409eff', // 主要按钮的背景色
    priBtnHover: '#66b1ff', // 主要按钮的悬浮、聚焦背景色
  },
  {
    themeId: 1,
    primaryBtn: '#67c23a',
    priBtnHover: '#85ce61',
  },
  {
    themeId: 2,
    primaryBtn: '#e6a23c',
    priBtnHover: '#ebb563',
  },
];

export default colors;

3.通过 ajax 获取 theme.css ,将颜色值替换为关键词。

data() {
  return {
    active: 0,
    themeStyleStr: '', // 存放 替换成关键词的 theme.css 内容
    colors: themeColors, // 所有可选的主题颜色数组。即:theme-colors.js 文件export的数组
  };
},
mounted() {
  // 通过 ajax 获取 theme.css 的内容,并将颜色值替换为关键词
  this.$http.getThemeFile().then(res => {
    this.themeStyleStr = this.getStyleTemplate(res);
  });
},
methods: {
  // 获取样式模板:将颜色值替换为关键词。
  getStyleTemplate(data) {
    let color = this.colors[0];
    delete color.themeId;
    let colorMap = {};
    Object.keys(color).forEach(key => {
      colorMap[color[key]] = key;
    });
    Object.keys(colorMap).forEach(key => {
      data = data.replace(new RegExp(key, 'ig'), colorMap[key]);
    });
    return data;
  },
}

this.$http.getThemeFile 方法

// 使用原生ajax获取换肤的样式文件
getThemeFile() {
  return new Promise(resolve => {
    const url = location.origin + '/static/styles/theme.css';
    const xhr = new XMLHttpRequest();
    xhr.onreadystatechange = () => {
      if (xhr.readyState === 4 && xhr.status === 200) {
        resolve(xhr.responseText);
      }
    };
    xhr.open('GET', url);
    xhr.send();
  });
}

4.把关键词再换回刚刚生成的相应的颜色值,并在页面上添加 style 标签

methods: {
  // 点击切换主题
  changeTheme(index) {
    this.active = index;
    this.setNewStyle(this.themeStyleStr, this.colors[index]);
  },
  // 根据选择的主题颜色,把关键词换成相应的主题颜色,并在页面上添加 style 标签
  setNewStyle(originalStyle, colors) {
    let oldEl = document.getElementById('theme-style');
    let cssText = originalStyle;
    Object.keys(colors).forEach(key => {
      cssText = cssText.replace(new RegExp(key, 'ig'), colors[key]);
    });
    const style = document.createElement('style');
    style.innerHTML = cssText;
    style.id = 'theme-style';
    oldEl ? document.head.replaceChild(style, oldEl) : document.head.appendChild(style);
  }
}

图片图标切换

1.图片切换和图标切换是同样的原理。在之前新建好的 theme.scss 文件追加图标引入的样式。

.theme-test-icon {
  background: url("/static/images/common/list-modify-icon.svg");
}

2.在之前新建好的 theme-colors.js 文件追加图标路径

/*图片统一使用一个路径,更换主题时需要在images文件夹下新建主题文件夹,与原始路径对应,图片文件名须一致
应避免 primaryBtn 与 primaryBtnHover 同时出现,因为正则匹配 primaryBtn 会把 primaryBtnHover 部分匹配出来,达不到效果*/
const colors = [
  {
    themeId: 0,
    primaryBtn: '#409eff', // 主要按钮的背景色
    priBtnHover: '#66b1ff', // 主要按钮的悬浮、聚焦背景色
    imagePath: '/static/images', // 图片绝对路径
  },
  {
    themeId: 1,
    primaryBtn: '#67c23a',
    priBtnHover: '#85ce61',
    imagePath: '/static/images/theme1',
  },
  {
    themeId: 2,
    primaryBtn: '#e6a23c',
    priBtnHover: '#ebb563',
    imagePath: '/static/images/theme2',
  },
];
export default colors;

3.引入需要主题切换的图片/图标,存放于 /static/images/ 之下,每个额外的主题图片需要一个文件夹进行存放,例如 /theme1 或者 /theme2。注意:各个主题的图片文件名要保持不变;图片路径是根据 theme.scss 里面引入图片样式的路径来决定的,可以根据项目实际情况进行调整。

详解Vue 换肤方案验证

以上,就是Vue项目实现换肤功能的一种方案。换肤功能的实现还有其他方法,欢迎一起交流学习。

Javascript 相关文章推荐
限制复选框的最大可选数
Jul 01 Javascript
向大师们学习Javascript(视频与PPT)
Dec 27 Javascript
JS字符串处理实例代码
Aug 05 Javascript
js单例模式详解实例
Nov 21 Javascript
运用JQuery的toggle实现网页加载完成自动弹窗
Mar 18 Javascript
JavaScript实现简单图片滚动附源码下载
Jun 17 Javascript
JavaScript实现的GBK、UTF8字符串实际长度计算函数
Aug 27 Javascript
浅谈javascript的Array.prototype.slice.call
Aug 31 Javascript
JS中mouseup事件丢失的原因与解决办法
Jun 14 Javascript
基于cropper.js封装vue实现在线图片裁剪组件功能
Mar 01 Javascript
element-ui组件中input等的change事件中传递自定义参数
May 22 Javascript
原生Javascript+HTML5一步步实现拖拽排序
Jun 12 Javascript
Vue项目实现换肤功能的一种方案分析
Aug 28 #Javascript
js遍历详解(forEach, map, for, for...in, for...of)
Aug 28 #Javascript
Angular6使用forRoot() 注册单一实例服务问题
Aug 27 #Javascript
jQuery - AJAX load() 实例用法详解
Aug 27 #jQuery
JS实现提示框跟随鼠标移动
Aug 27 #Javascript
js对象数组和对象的使用实例详解
Aug 27 #Javascript
vue递归组件实战之简单树形控件实例代码
Aug 27 #Javascript
You might like
THINKPHP项目开发中的日志记录实例分析
2014/12/01 PHP
apache中为php 设置虚拟目录
2014/12/17 PHP
分享PHP守护进程类
2015/12/30 PHP
浅谈PHP中其他类型转化为Bool类型
2016/03/28 PHP
php array_merge_recursive 数组合并
2016/10/26 PHP
基于jQuery的合并表格中相同文本的相邻单元格的代码
2011/04/06 Javascript
window.requestAnimationFrame是什么意思,怎么用
2013/01/13 Javascript
可插入图片的TEXT文本框
2013/12/27 Javascript
jquery的总体架构分析及实现示例详解
2014/11/08 Javascript
快速获取/设置iframe内对象元素的几种js实现方法
2016/05/20 Javascript
BootStrap selectpicker
2016/06/20 Javascript
javascript动画之模拟拖拽效果篇
2016/09/26 Javascript
AngularJS使用ng-app自动加载bootstrap框架问题分析
2017/01/04 Javascript
JavaScript无操作后屏保功能的实现方法
2017/07/04 Javascript
Angular2管道Pipe及自定义管道格式数据用法实例分析
2017/11/29 Javascript
javascript代码优化的8点总结
2018/01/29 Javascript
JavaScript实现区块链
2018/03/14 Javascript
动态加载、移除js/css文件的示例代码
2018/03/20 Javascript
JavaScript树的深度优先遍历和广度优先遍历算法示例
2018/07/30 Javascript
微信小程序以7天为周期连续签到7天功能效果的示例代码
2020/08/20 Javascript
在Docker上部署Python的Flask框架的教程
2015/04/08 Python
Python开发的HTTP库requests详解
2017/08/29 Python
Python实现的计算马氏距离算法示例
2018/04/03 Python
numpy判断数值类型、过滤出数值型数据的方法
2018/06/09 Python
pygame实现俄罗斯方块游戏
2018/06/26 Python
pycharm中成功运行图片的配置教程
2018/10/28 Python
详解numpy.meshgrid()方法使用
2019/08/01 Python
Python中Qslider控件实操详解
2021/02/20 Python
html5开发三八女王节表白神器
2018/03/07 HTML / CSS
新加坡领先的时尚生活方式零售品牌:CHARLES & KEITH
2018/01/16 全球购物
构建高效课堂实施方案
2014/03/13 职场文书
消防安全宣传标语
2014/06/07 职场文书
师范大学生求职信
2014/06/13 职场文书
纪律教育月活动总结
2014/08/26 职场文书
装修安全责任协议书
2016/03/22 职场文书
php中配置文件保存修改操作 如config.php文件的读取修改等操作
2021/05/12 PHP