主题化管理经常能在网站上看到,一般的思路都是将主题相关的CSS样式独立出来,在用户选择主题的时候加载相应的CSS样式文件。现在大部分浏览器都能很好的兼容CSS变量,主题化样式更容易管理了。最近,使用CSS变量在Vue项目中做了一个主题化实践,下面来看看整个过程。

Github项目地址

演示地址

可行性测试

为了检验方法的可行性,在public文件夹下新建一个themes文件夹,并在themes文件夹新建一个default.css文件:

:root {
--color: red;
}

在public文件夹的index.html文件中引入外部样式theme.css,如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>vue-skin-peeler-demo</title>
<!-- 引入themes文件夹下的default.css -->
<link rel="stylesheet" type="text/css" href="src/themes/default.css" rel="external nofollow">
</head>
<body>
<noscript>
<strong>We're sorry but vue-skin-peeler-demo doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

然后,在Home.vue中使用CSS变量:

<template>
<div class="home">
<div :class="$style.demo">变红色</div>
</div>
</template> <script>
export default {
name: 'home'
}
</script> <style module lang="scss">
.demo {
color: var(--color);
}
</style>

然后,运行项目并在浏览器中打开页面,页面显示效果正常。

注意:@vue/cli使用link标签引入css样式可能报错“We're sorry but vue-skin-peeler-demo doesn't work properly without JavaScript enabled. Please enable it to continue.”。这是因为@vue/cli将src目录下的文件都通过webpack打包所引起,所以,静态文件资源要放在public(如果是@vue/cli 2.x版本放在static)文件夹下。

实现主题切换

这里主题切换的思路是替换link标签的href属性,因此,需要写一个替换函数,在src目录下新建themes.js文件,代码如下:

// themes.js
const createLink = (() => {
let $link = null
return () => {
if ($link) {
return $link
}
$link = document.createElement('link')
$link.rel = 'stylesheet'
$link.type = 'text/css'
document.querySelector('head').appendChild($link)
return $link
}
})() /**
* 主题切换函数
* @param {string} theme - 主题名称, 默认default
* @return {string} 主题名称
*/
const toggleTheme = (theme = 'default') => {
const $link = createLink()
$link.href = `./themes/${theme}.css`
return theme
} export default toggleTheme

然后,在themes文件下创建default.css和dark.css两个主题文件。创建CSS变量,实现主题化。CSS变量实现主题切换请参考另一篇文章初次接触css变量

兼容性

IE浏览器以及一些旧版浏览器不支持CSS变量,因此,需要使用css-vars-ponyfill,是一个ponyfill,可在旧版和现代浏览器中为CSS自定义属性(也称为“ CSS变量”)提供客户端支持。由于要开启watch监听,所以还有安装MutationObserver.js

安装:

npm install css-vars-ponyfill mutationobserver-shim --save

然后,在themes.js文件中引入并使用:

// themes.js
import 'mutationobserver-shim'
import cssVars from 'css-vars-ponyfill' cssVars({
watch: true
}) const createLink = (() => {
let $link = null
return () => {
if ($link) {
return $link
}
$link = document.createElement('link')
$link.rel = 'stylesheet'
$link.type = 'text/css'
document.querySelector('head').appendChild($link)
return $link
}
})() /**
* 主题切换函数
* @param {string} theme - 主题名称, 默认default
* @return {string} 主题名称
*/
const toggleTheme = (theme = 'default') => {
const $link = createLink()
$link.href = `./themes/${theme}.css`
return theme
} export default toggleTheme

开启watch后,在IE 11浏览器点击切换主题开关不起作用。因此,每次切换主题时都重新执行cssVars(),还是无法切换主题,原因是开启watch后重新执行cssVars()是无效的。最后,只能先关闭watch再重新开启。成功切换主题的themes.js代码如下:

// themes.js
import 'mutationobserver-shim'
import cssVars from 'css-vars-ponyfill' const createLink = (() => {
let $link = null
return () => {
if ($link) {
return $link
}
$link = document.createElement('link')
$link.rel = 'stylesheet'
$link.type = 'text/css'
document.querySelector('head').appendChild($link)
return $link
}
})() /**
* 主题切换函数
* @param {string} theme - 主题名称, 默认default
* @return {string} 主题名称
*/
const toggleTheme = (theme = 'default') => {
const $link = createLink()
$link.href = `./themes/${theme}.css`
cssVars({
watch: false
})
setTimeout(function () {
cssVars({
watch: true
})
}, 0)
return theme
} export default toggleTheme

查看所有代码,请移步Github项目地址

记住主题

实现记住主题这个功能,一是可以向服务器保存主题,一是使用本地存储主题。为了方便,这里主要使用本地存储主题的方式,即使用localStorage存储主题。具体实现请移步Github项目地址

Vue项目使用CSS变量实现主题化的更多相关文章

  1. <转载> VUE项目中CSS管理

    vue的scoped 在vue项目中,当 .vue文件中 <style> 标签有 *scoped 属性时,它的 CSS 只作用于当前组件中的元素,很好的实现了样式私有化的目的. 使用sco ...

  2. 关于使用css变量实现主题的切换效果

    现在要实现网页主题的切换成本较小的一种方案就是使用css的变量来实现 HTML 在HTML的body标签上先定义一个id元素属性 <body id="sm-theme"> ...

  3. vue项目的环境变量

    关于项目中环境变量的总结 背景 项目环境一般分为开发环境,测试环境,线上环境 因为每个环境的接口域名.webpack 配置都是不同的,所以在打包构建时,我们需要区分这些环境,这时就用到了环境变量 在工 ...

  4. 解决vue项目中使用ivew定制主题报 .bezierEasingMixin();错误

    背景:在使用view-design(iview)定制主体时(覆盖变量方式)出现less错误 完整错误如下 解决方法: 在vue.config.js中添加 less-loader:5.0.x modul ...

  5. vue项目中使用组件化开发

    最近在使用vue-cli结合webpack打包工具开发一个后台管理系统,使用vue难免需要运用组件化思想,而这也正是vue的一大特点. 在之前做的vue项目中,稍微有一点组件化的思想,可能是对组件化不 ...

  6. 初次接触CSS变量

    本文的目的主要是展示CSS变量是如何工作的.随着Web应用程序变得越来越大,CSS变得越来越大,越来越多,而且很多时候都很乱,在良好的上下文中使用CSS变量,为您提供重用和轻松更改重复出现的CSS属性 ...

  7. python 全栈开发,Day58(bootstrap组件,bootstrap JavaScript 插件,后台模板,图表插件,jQuery插件库,Animate.css,swiper,运行vue项目)

    一.bootstrap组件 无数可复用的组件,包括字体图标.下拉菜单.导航.警告框.弹出框等更多功能. 组件和插件的区别? 插件:一个功能,比如js文件 组件:html css js 组件包含插件 面 ...

  8. vue项目中postcss-pxtorem的使用及webpack中的配置 css中单位px和em,rem的区别

    移动手机版要求我们在制作嵌入h5的时候去适配不同的手机.适配有多重模式,有flex.百分比等.字体大小的控制也有px.百分比.rem等单位,webpack中 px转rem. vue项目中postcss ...

  9. vue-cli构建的vue项目打包后css引入的背景图路径不对的问题

    使用vue-cli构建vue项目后,再打包遇到一个css引入的背景图片路径的问题,就是css代码中背景图片是根据相对路径来写的,如下图: 当使用npm run dev命令本地访问的时候,背景图片是正常 ...

随机推荐

  1. 【Labview入门】工具的使用

    labview版本:Labview2015 在你使用labview时你可能已经发现,在鼠标移动到连线上时,鼠标会自动的变化,其实这是你选择了自动识别的工具,然后鼠标会根据你所指示的东西自动切换工具类型 ...

  2. selenium-模块概述(1)

    Selenium是一个用于Web应用程序自动化测试工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样. 1.目录结构如下: D:\soft\python36\Lib\site-pa ...

  3. ASP.NET Core 3.0 一个 jwt 的轻量角色/用户、单个API控制的授权认证库

    目录 说明 一.定义角色.API.用户 二.添加自定义事件 三.注入授权服务和中间件 三.如何设置API的授权 四.添加登录颁发 Token 五.部分说明 六.验证 说明 ASP.NET Core 3 ...

  4. Java描述设计模式(16):代理模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景 1.场景描述 在电商高速发展的今天,快递的数量十分庞大,甚至出现了快递代理行业,简单的说就是快递的主人没有时间收快递,会指定一个 ...

  5. 解析 Microsoft.Extensions.DependencyInjection 2.x 版本实现

    项目使用了 Microsoft.Extensions.DependencyInjection 2.x 版本,遇到第2次请求时非常高的内存占用情况,于是作了调查,本文对 3.0 版本仍然适用. 先说结论 ...

  6. javascript单线程,异步与执行机制

    js的单线程模型与游览器的进程/线程息息相关,在了解js单线程与异步的时候,建议先看看这篇文章 为什么是单线程 由于js是可操作dom的,如果js是多线程,在多线程的交互下,处于界面中的dom节点就可 ...

  7. markdown语法(转)

    markdown语法 1.标题代码 # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 ###### 六级标题 2.引用代码 >你好 >> 您好 ...

  8. .NET webAPI中集成swagger

    最近做的项目使用winform三层+webapi,对于webAPI路由文档管理一直觉得单独做一些管理比较麻烦,并且测试的时候项目内的代码测试运行起来也比较麻烦,所以在网上开始检索相关办法,发现热度比较 ...

  9. Kong05-Kong 的健康检查和监控

    您可以让 Kong 代理的 API 使用 ring-balancer , 通过添加包含一个或多个目标实体的upstream 实体来配置,每个目标指向不同的IP地址(或主机名)和端口.ring-bala ...

  10. [爬虫]用python的requests模块爬取糗事百科段子

    虽然Python的标准库中 urllib2 模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests 自称 “HTTP for Humans”,说明使用更 ...