详解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 相关文章推荐
用js判断浏览器是否是IE的比较好的办法
May 08 Javascript
JavaScript asp.net 获取当前超链接中的文本
Apr 14 Javascript
js模拟点击以提交表单为例兼容主流浏览器
Nov 29 Javascript
JQuery中DOM加载与事件执行实例分析
Jun 13 Javascript
通过点击jqgrid表格弹出需要的表格数据
Dec 02 Javascript
jquery淡入淡出效果简单实例
Jan 14 Javascript
简单实现js无缝滚动效果
Feb 05 Javascript
Linux使用Node.js建立访问静态网页的服务实例详解
Mar 21 Javascript
微信小程序 wx.request方法的异步封装实例详解
May 18 Javascript
原生js中ajax访问的实例详解
Sep 19 Javascript
在iFrame子页面里实现模态框的方法
Aug 17 Javascript
JS实现碰撞检测效果
Mar 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
PHP 数字左侧自动补0
2008/03/31 PHP
PHP 日期时间函数的高级应用技巧
2009/10/10 PHP
PHP 手机归属地查询 api
2010/02/08 PHP
10个简化PHP开发的工具
2014/12/25 PHP
dedecms集成财付通支付接口
2014/12/28 PHP
微信支付PHP SDK ―― 公众号支付代码详解
2016/09/13 PHP
jquery获取下拉列表的值为null的解决方法
2011/03/18 Javascript
ASP.NET jQuery 实例10 动态修改hyperlink的URL值
2012/02/03 Javascript
基于JavaScript 数据类型之Boolean类型分析介绍
2013/04/19 Javascript
js格式化货币数据实现代码
2013/09/04 Javascript
jquery获取子节点和父节点的示例代码
2013/09/10 Javascript
JavaScript创建闭包的两种方式的优劣与区别分析
2015/06/22 Javascript
Extjs4.0 ComboBox如何实现三级联动
2016/05/11 Javascript
JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法
2016/05/19 Javascript
AngularJS 过滤器的简单实例
2016/07/27 Javascript
Vue2单一事件管理组件通信
2017/05/09 Javascript
angularjs中判断ng-repeat是否迭代完的实例
2018/09/12 Javascript
详解JS判断页面是在手机端还是在PC端打开的方法
2019/04/26 Javascript
layer弹出框确定前验证:弹出消息框的方法(弹出两个layer)
2019/09/21 Javascript
vue实现鼠标移过出现下拉二级菜单功能
2019/12/12 Javascript
Vue中axios拦截器如何单独配置token
2019/12/27 Javascript
Vue v-model组件封装(类似弹窗组件)
2020/01/08 Javascript
[02:00]最后,我终于出了辉耀
2018/03/27 DOTA
Python编程实现生成特定范围内不重复多个随机数的2种方法
2017/04/14 Python
Python使用ctypes调用C/C++的方法
2019/01/29 Python
Django组件cookie与session的具体使用
2019/06/05 Python
Django Session和Cookie分别实现记住用户登录状态操作
2020/07/02 Python
CSS3中几个新增加的盒模型属性使用教程
2016/03/01 HTML / CSS
CSS3实现多重边框的方法总结
2016/05/31 HTML / CSS
全球最大的瓷器、水晶和银器零售商:Replacements
2020/06/15 全球购物
财务管理个人自荐书范文
2013/11/24 职场文书
义和团口号
2014/06/17 职场文书
十一国庆节“向国旗敬礼”主题班会活动方案
2014/09/27 职场文书
实习生个人总结范文
2015/02/28 职场文书
民事诉讼代理词
2015/05/25 职场文书
sqlserver2017共享功能目录路径不可改的解决方法
2021/04/16 SQL Server