Vue项目实现换肤功能的一种方案分析


Posted in Javascript onAugust 28, 2019

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

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

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 相关文章推荐
解决FireFox下[使用event很麻烦]的问题
Nov 26 Javascript
基于jquery的获取浏览器窗口大小的代码
Mar 28 Javascript
javascript复制对象使用说明
Jun 28 Javascript
jQuery实现图片放大预览实现原理及代码
Sep 12 Javascript
项目中常用的JS方法整理
Jan 30 Javascript
基于javascript实现checkbox复选框实例代码
Jan 28 Javascript
JavaScript学习笔记之数组的增、删、改、查
Mar 23 Javascript
jQuery插件扩展操作入门示例
Jan 16 Javascript
如何给ss bash 写一个 WEB 端查看流量的页面
Mar 23 Javascript
如何使用webpack打包一个库library的方法步骤
Dec 18 Javascript
Vue引入Stylus知识点总结
Jan 16 Javascript
Nuxt页面级缓存的实现
Mar 09 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
vue项目中引入Sass实例方法
Aug 27 #Javascript
You might like
PHP的开发框架的现状和展望
2007/03/16 PHP
php设计模式 State (状态模式)
2011/06/26 PHP
PHP Yii框架之表单验证规则大全
2015/11/16 PHP
各种快递查询--Api接口
2016/04/26 PHP
ThinkPHP整合datatables实现服务端分页的示例代码
2018/02/10 PHP
PHP连续签到功能实现方法详解
2019/12/04 PHP
javascript 避免闭包引发的问题
2009/03/17 Javascript
JavaScript插件化开发教程 (二)
2015/01/27 Javascript
jquery左右全屏大尺寸多图滑动效果代码分享
2015/08/28 Javascript
获取JS中网页各种高宽与位置的方法总结
2016/07/27 Javascript
JS实现的适合做faq或menu滑动效果示例
2016/11/17 Javascript
JavaScript错误处理和堆栈追踪详解
2017/04/18 Javascript
Vue2.0基于vue-cli+webpack同级组件之间的通信教程(推荐)
2017/09/14 Javascript
基于vue2实现左滑删除功能
2017/11/28 Javascript
浅析Node.js非对称加密方法
2018/01/29 Javascript
jQuery实现炫丽的3d旋转星空效果
2018/07/04 jQuery
vue中的计算属性和侦听属性
2020/11/06 Javascript
vue中defineProperty和Proxy的区别详解
2020/11/30 Vue.js
Python中__name__的使用实例
2015/04/14 Python
使用python存储网页上的图片实例
2018/05/22 Python
对numpy中的where方法嵌套使用详解
2018/10/31 Python
Python中的取模运算方法
2018/11/10 Python
python pygame实现五子棋小游戏
2020/10/26 Python
更新pip3与pyttsx3文字语音转换的实现方法
2019/08/08 Python
Python容器使用的5个技巧和2个误区总结
2019/09/26 Python
Python任务自动化工具tox使用教程
2020/03/17 Python
python中rb含义理解
2020/06/18 Python
使用CSS3和Checkbox实现JQuery的一些效果
2015/08/03 HTML / CSS
html5本地存储 localStorage操作使用详解
2016/09/20 HTML / CSS
材料采购员岗位职责
2013/12/17 职场文书
纺织工程专业个人求职信范文
2014/01/27 职场文书
什么是就业协议书
2014/04/17 职场文书
2015年度村委会工作总结
2015/04/29 职场文书
金砖之国观后感
2015/06/11 职场文书
2019年行政人事个人工作总结范本!
2019/07/19 职场文书
索尼ICF-5900W收音机测评
2022/04/24 无线电