vue+webpack 更换主题N种方案优劣分析


Posted in Javascript onOctober 28, 2019

需求:由于业务需要,我们需要做多套皮肤

调研了下当前行业的实现方案,五花八门良莠不齐,在此总结下各种方案有优劣及复杂度,供大家快速定位到符合自己业务的方案,以vue 单页应用为业务场景

方式一:class切换方式

实现:

在每个需要更换的页面定义多个class,根据运行时标识动态的切换class名称实现加载不同的样式,这种方式较为简单

优点:

  • 不需要修改构建工具相关
  • 业务开发过程可以实现,没有限制
  • 支持动态切换

缺点:

  • 逻辑分散耦合在各个页面,一旦需要修改,涉及修改的页面较多
  • 代码需要预先内置,不支持动态颜色修改

方式二:ElementUI的实现

实现:

对主题涉及的颜色使用特殊值

如:UI需要白色#ffffff色值的时候使用一个相近的特征值颜色 如:#fffffe

// 将默认样式特征值替换为变量,用于多次替换
   getStyleTemplate(data) {
    const colorMap = {
     '#fffffe': 'text_color'
    };
    Object.keys(colorMap).forEach(key => {
     const value = colorMap[key];
     data = data.replace(new RegExp(key, 'ig'), value);
    });
    return data;
   },

在代码运行时动态获取到需要修改的颜色值

如: 需要修改#fffffe =》 #ff00ff

// 通过用户操作或者接口,获取到要替换的色值
 colors:{
     text_color: '#ff00ff'
    }

查找页面所有style标签将其色值#fffffe正则匹配出来,替换为 #ff00ff

// 获取默认样式,可以从已加载的 style 中获取也可以从 css link 获取
   getIndexStyle() {
    document.querySelectorAll('style').forEach(item=>{
     this.originalStyle += this.getStyleTemplate(item.textContent);
    })
   },
   getCssLink(){
     this.get('./cssPath.css').then(json=>{
       this.originalStyle = this.getStyleTemplate(json.data);
     })
   }

在页面新加标签style覆盖默认值

// 替换默认样式表,插入 style 标签覆盖样式
   writeNewStyle() {
    let cssText = this.originalStyle;
    log(cssText)
    Object.keys(this.colors).forEach(key => {
     cssText = cssText.replace(new RegExp('(:|\\s+)' + key, 'g'), '$1' + this.colors[key]);
    });
    cssText = cssText.replace(/\n/g,'')
    if (this.originalStylesheetCount === document.styleSheets.length) {
     const style = document.createElement('style');
     style.innerText = cssText;
     document.head.appendChild(style);
    } else {
     document.head.lastChild.innerText = cssText;
    }
   },

优点:

  • 支持动态切换
  • 支持动态色值
  • 不需要内置多份样式

缺点:

  • 业务开发过程中需要对ui给出的色值重定义,业务开发需要有一定的规则
  • 无法修改背景图片
  • 无法对懒加载的样式做处理,需要初始化加载全局所有样式
const ExtractTextPlugin = require('extract-text-webpack-plugin')

// 抽离css
 module: {
 loaders: [
      {//抽离css 通过link加载
        test: /\.css$/,
        loader: ExtractTextPlugin.extract({ 
        fallback: 'style-loader', 
        use: 'css-loader'
        })
      }
      ...
      
 plugins: [
    new ExtractTextPlugin({ 
    filename: 'css/[name].css'
    allChunks: true // 打包所有页面css到同一个css 文件
    })
  ]
  • 无法动态修改背景图片

方式三:编译时多主题全量构建

实现:

  • 定义多套样式
  • 构建时将多套样式主题作为独立构建入口,构建出主题静态文件css文件
  • 业务运行时动态加载不同的主题文件

优点:

  • 支持动态切换主题
  • 业务开发样式分离
  • 编译时构建性能较好 缺点:
  • 构建工具配置较为复杂,适用单入口应用,对多入口的支持不友好
  • 需要定义全局 less 文件,在入口引入
  • 业务需要额外操作

配合 rel="alternate stylesheet" 可预加载备选主题样式

方式四: 编译时选择性构建

实现:

  • 内置多套皮肤
  • 构建时传入参数,根据不同的构建参数加载不同的主题样式文件

优点:

  • 构建工具配置较为简单,不需要业务做额外操作
  • 多入口应用支持度好

缺点:

  • 不支持动态切换
  • 多个项目需要构建多次,需要构建系统支持

方式五:less动态变量

实现:

  • 修改构建脚本,将所有页面less文件抽到同一个文件中
  • 不编译less,页面直接加载less文件
  • 使用less.js 在客户端编译less 文件
less: {
    modifyVars: {},
    javascriptEnabled: true
   }

优点:

  • 支持动态切换
  • 支持动态色值

缺点:

  • 客户端编译较耗性能/耗时
  • 需要额外加载less.js mini文件size: 131KB

方式六:css变量

实现:

在需要变化的css属性定义变量

:root {
 --main-bg-color: pink;
}

body {
 background-color: var(--main-bg-color);
}

在运行时动态的修改变量

document.body.style.setProperty('--primary', '#7F583F');

优点:

  • 浏览器原生支持,无需额外操作
  • 支持动态色值

缺点:

  • 低版本兼容性不好 ios Safari 9.3、 android 5、 chrome forAndroid 76

UC、QQ、Baidu 等国内浏览器支持度较差

方式七: import动态加载

实现:

  • 业务中预定义多套主题
  • 运行时根据变量动态加载对应主题
if(a){
  import('./thems/a/base.less')
}else if(b){
   import('./thems/b/base.less')
}

优点:

  • 支持动态切换
  • 实现简单

缺点:

  • 不支持动态色值
  • 需要全局定义多套样式表
  • 全局定义 class 无法定义变量在 vue style 中引用变量

方式 动态切换 动态色值 支持变量 实现复杂度 兼容性 性能 维护性
class切换方式 简单 良好 良好
ElementUI的实现 中等 良好 一般
编译时多主题全量构建 复杂 良好 一般
编译时选择性构建 中等 良好 良好
less变量 复杂 良好
css变量 中等 良好
import动态加载 简单 良好 良好

注:

  • 动态切换:是否支持在运行时切换皮肤
  • 动态设置:是否支持在运行时动态设置皮肤颜色
  • 支持变量:是否可以再全局定义变量 less 文件,然后在不同的页面引用 less,依赖其中的变量,还是需要在全局 less 文件里面定义全局 class
  • 实现复杂度: 需要修改的代码量包括构建工具和业务代码
  • 兼容性: 主流浏览器支持程度
  • 性能:包括代码的首屏加载的 size、切换的速度、切换的时候会不会有闪动

参考资料:

https://panjiachen.github.io/vue-element-admin-site/zh/guide/advanced/theme.html#样式覆盖
https://developer.mozilla.org/zh-CN/docs/Web/CSS/Alternative_style_sheets
https://less.bootcss.com

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Extjs学习笔记之七 布局
Jan 08 Javascript
ie下动态加态js文件的方法
Sep 13 Javascript
javascript移出节点removeChild()使用介绍
Apr 03 Javascript
js在指定位置增加节点函数insertBefore()用法实例
Jan 12 Javascript
jQuery基于ajax实现带动画效果无刷新柱状图投票代码
Aug 10 Javascript
jquery实现一个简单的表单验证实例
Mar 30 Javascript
利用canvas中toDataURL()将图片转为dataURL(base64)的方法详解
Nov 20 Javascript
浅谈vuex 闲置状态重置方案
Jan 04 Javascript
vue router嵌套路由在history模式下刷新无法渲染页面问题的解决方法
Jan 25 Javascript
Vue2.0+Vux搭建一个完整的移动webApp项目的示例
Mar 19 Javascript
JavaScript 实现同时选取多个时间段的方法
Oct 17 Javascript
vue使用echarts实现水平柱形图实例
Sep 09 Javascript
使用Vue调取接口,并渲染数据的示例代码
Oct 28 #Javascript
JavaScript 反射和属性赋值实例解析
Oct 28 #Javascript
vue 解决数组赋值无法渲染在页面的问题
Oct 28 #Javascript
在vue中把含有html标签转为html渲染页面的实例
Oct 28 #Javascript
详解关闭令人抓狂的ESlint 语法检测配置方法
Oct 28 #Javascript
Vue实现将数据库中带html标签的内容输出(原始HTML(Raw HTML))
Oct 28 #Javascript
js实现图片无缝循环轮播
Oct 28 #Javascript
You might like
php中用于检测一个地理IP地址是否可用的代码
2012/02/19 PHP
php 的加密函数 md5,crypt,base64_encode 等使用介绍
2012/04/09 PHP
thinkphp控制器调度使用示例
2014/02/24 PHP
谈谈PHP中substr和substring的正确用法及相关参数的介绍
2015/12/16 PHP
PHP的Yii框架中YiiBase入口类的扩展写法示例
2016/03/17 PHP
深入理解PHP之源码目录结构与功能说明
2016/06/01 PHP
php使用ftp实现文件上传与下载功能
2017/07/21 PHP
javascript实现div的显示和隐藏的小例子
2013/06/25 Javascript
Windows8下搭建Node.js开发环境教程
2014/09/03 Javascript
jQuery中extend函数详解
2015/02/13 Javascript
jquery实现点击弹出带标题栏的弹出层(从右上角飞入)效果
2015/09/19 Javascript
轻松学习Javascript闭包函数
2015/12/15 Javascript
AngularJS中的Promise详细介绍及实例代码
2016/12/13 Javascript
HTML5 js实现拖拉上传文件功能
2020/11/20 Javascript
微信小程序实现下拉刷新和轮播图效果
2017/11/21 Javascript
微信小程序五子棋游戏的棋盘,重置,对弈实现方法【附demo源码下载】
2019/02/20 Javascript
详解JavaScript实现动态的轮播图效果
2019/04/29 Javascript
package.json各个属性说明详解
2020/03/11 Javascript
[01:35]2018完美盛典章节片——共竞
2018/12/17 DOTA
Python用list或dict字段模式读取文件的方法
2017/01/10 Python
浅谈Python中的可变对象和不可变对象
2017/07/07 Python
python3+PyQt5实现支持多线程的页面索引器应用程序
2018/04/20 Python
python 去除txt文本中的空格、数字、特定字母等方法
2018/07/24 Python
Python实现一个数组除以一个数的例子
2019/07/20 Python
python使用pygame实现笑脸乒乓球弹珠球游戏
2019/11/25 Python
使用python修改文件并立即写回到原始位置操作(inplace读写)
2020/06/28 Python
浅析Python 抽象工厂模式的优缺点
2020/07/13 Python
Ratchet 模态框的实现
2020/08/19 HTML / CSS
求网格中的黑点分布
2013/11/06 面试题
局域网标准
2016/09/10 面试题
普通党员四风问题对照检查材料
2014/09/27 职场文书
社区活动总结
2015/02/04 职场文书
工作经历证明范本
2015/06/15 职场文书
python实现批量提取指定文件夹下同类型文件
2021/04/05 Python
Python爬虫之爬取哔哩哔哩热门视频排行榜
2021/04/28 Python
Smart 2 车辆代号 HC11 全新谍照曝光
2022/04/21 数码科技