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

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

调研了下当前行业的实现方案,五花八门良莠不齐,在此总结下各种方案有优劣及复杂度,供大家快速定位到符合自己业务的方案,以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

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

(0)

相关推荐

  • Vue的elementUI实现自定义主题方法

    使用vue开发项目,用到elementUI,根据官网的写法,我们可以自定义主题来适应我们的项目要求,下面来介绍一下两种方法实现的具体步骤,(可以参考官方文档自定义主题官方文档),先说项目中没有使用scss编写,用主题工具的方法(使用的较多) 第一种方法:使用命令行主题工具 使用vue-cli安装完项目并引入element-ui(具体可参考第二种方法中的介绍) 一.安装工具 1,安装主题工具 npm i element-theme -g 2,安装chalk主题,可以从 npm 安装或者从 GitH

  • vue如何根据网站路由判断页面主题色详解

    前言 本文主要介绍的是vue根据网站路由判断页面主题色的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 需求: 不同品牌对应不同版本配色 做法: 根据域名带的参数判断进入哪个品牌,对应哪个版本 在main.js中 import Vue from 'vue' import App from './App' import router from './router' import axios from 'axios' import MintUI from 'mint-ui'

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

    需求:由于业务需要,我们需要做多套皮肤 调研了下当前行业的实现方案,五花八门良莠不齐,在此总结下各种方案有优劣及复杂度,供大家快速定位到符合自己业务的方案,以vue 单页应用为业务场景 方式一:class切换方式 实现: 在每个需要更换的页面定义多个class,根据运行时标识动态的切换class名称实现加载不同的样式,这种方式较为简单 优点: 不需要修改构建工具相关 业务开发过程可以实现,没有限制 支持动态切换 缺点: 逻辑分散耦合在各个页面,一旦需要修改,涉及修改的页面较多 代码需要预先内置,

  • 浅谈MYSQL中树形结构表3种设计优劣分析与分享

    目录 简介 问题 设计1:邻接表 表设计 SQL示例 设计2:路径枚举 表设计 SQL示例 设计3:闭包表 表设计 SQL示例 结合使用 表设计 总结 简介 在开发中经常遇到树形结构的场景,本文将以部门表为例对比几种设计的优缺点: 问题 需求背景:根据部门检索人员, 问题:选择一个顶级部门情况下,跨级展示当前部门以及子部门下的所有人员,表怎么设计更合理 ? 递归吗 ?递归可以解决,但是势必消耗性能 设计1:邻接表 注:(常见父Id设计) 表设计 CREATE TABLE `dept_info01

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

    需求:网站换肤,主题切换.网站的主题色可以在几种常用颜色之间进行切换,还有相关图片.图标也要跟随主题进行切换. 不多说,先看下最终的实现效果: 文章由两部分组成:css切换,图片图标切换 css切换 1.在 static 目录下新建一个 styles 文件夹,在 styles 下新建一个 theme.scss 文件(项目使用了sass,会自动编译成css文件,如果没有使用这些预处理工具可以直接新建 theme.css),将需要替换的 CSS 声明在此文件中. .theme-test-btn {

  • 使用vue打包时gzip压缩的两种方案

    目录 介绍两种gzip压缩的方式 webpack打包生成gz文件 服务器在线gzip压缩 vue项目开启gzip压缩 前端配置 后端配置 开局一张图: 可以看出,在项目部署后,我们的资源文件请求都会保持原本大小,如果文件过大,并且很多的情况下,会导致网络请求耗时,严重点可能阻塞后面的进程. 介绍两种gzip压缩的方式 1.打包的时候通过webpack配置生成对应的 .gz 文件,浏览器请求xx.js/css等文件时,服务器返回对应的xxx.js.gz文件: 2.浏览器请求xx.js文件时,服务器

  • vue+webpack实现异步加载三种用法示例详解

    1.第一例 const Home = resolve => { import("@/components/home/home.vue").then( module => { resolve(module) } } 注:(上面import的时候可以不写后缀) export default [{ path: '/home', name:'home', component: Home, meta: { requireAuth: true, // 添加该属性可以判断出该页面是否需要

  • vue 强制组件重新渲染(重置)的两种方案

    数据通过异步操作后,对之前刚加载的数据进行变更后,发现数据不能生效 方案一 当数据变更后,通过watch 监听,先去销毁当前的组件,然后再重现渲染.使用 v-if 可以解决这个问题 <template> <third-comp v-if="reFresh"/> </template> <script> export default{ data(){ return { reFresh:true, menuTree:[] } }, watch

  • vue打包上传服务器刷新404问题的两种方案

    一:nginx服务器解决方案,修改   .conf  配置文件 有两种解决方案 1: location / { try_files $uri $uri/ @router; index index.html; } location @router { rewrite ^.*$ /index.html last; } 2: location / { error_page 404 /index.html; #try_file $uri $uri/ /index.html =404; } 二:apach

  • 浅谈Vue单页面做SEO的四种方案

    目录 1.Nuxt 服务端渲染应用部署 (SSR服务器渲染) 优势: 不足:(开发中遇到的坑) 2.Nuxt 静态应用部署 优势: 不足: 3.预渲染prerender-spa-plugin 优势: 不足: 4.Phantomjs 针对爬虫做处理 优势: 不足: 总结 众所周知,Vue SPA单页面应用对SEO不友好,当然也有相应的解决方案,通过查找资料,大概有以下4种方法.(本人只用过第一,第三种方案) 1.Nuxt 服务端渲染应用部署 (SSR服务器渲染) 关于服务器渲染:Vue官网介绍 ,

  • Vue实现全局异常处理的几种方案

    目录 一.前端常见异常 二.实现简单的全局异常处理 三.Vue3 如何实现异常处理 四.总结 在开发组件库或者插件,经常会需要进行全局异常处理,从而实现:\ 全局统一处理异常: 为开发者提示错误信息: 方案降级处理等等. 那么如何实现上面功能呢?本文先简单实现一个异常处理方法,然后结合 Vue3 源码中的实现详细介绍,最后总结实现异常处理的几个核心. 本文 Vue3 版本为 3.0.11 一.前端常见异常 对于前端来说,常见的异常比较多,比如: JS 语法异常: Ajax 请求异常: 静态资源加

  • Vue.js项目前端多语言方案的思路与实践

    目录 一.通常有哪些内容需要处理 二.基本思路 三.具体实践中的一些细节 1.获取当前应该采用何种语言的getLang模块的实现 2.Vux组件的多语言包的配置 3.vux-loader的配置 4.自定义组件内外文案的多语言化 5.vuex-i18n的实现 6.图片的多语言化 7.在当前页面通过按钮切换当前语言后,如何更新当前页面的内容? 8.Yaml中特殊字符的转义 总结 前端的国际化是一个比较常见的需求.但网上关于这一方面的直接可用的方案却不多.最近刚做了一版基于Vue.js的多语言实现,在

随机推荐