问题解决|使用Less变量和媒体查询实现深浅色模式适配
使用Less变量简化css写法,并不影响css变量和媒体查询在深浅模式切换时的效果
<!--more-->分析问题
首先要清楚问题的来源是什么,使用媒体查询api可以根据深浅色为css变量赋予不同的值,而Less(或是scss)不是原生被浏览器所支持,运行时需要先转为为原生css,这一步也就是编译,有点类似ts和js的关系。这里采用的是vite创建的Vue3项目
而Less/Scss在编译的过程中,进行的是完全的字段替换,这也就意味着在运行之前css已经被固定,无法在运行的过程中动态修改,当然也不支持媒体查询的所有属性,但一些还是支持的哈,比如设备类型,最大宽度什么的,这里深浅色默认是不支持的。
问题出现
这里首先我是想办法完全使用Less的,也就是媒体查询+正常定义变量
但是实际测试中发现所编译出的css根本没有@media
的字样,所以又是inline编译了,导致完全写死,不可能在运行中改变
问题解决
因为测试Less写法一直有问题,而原生css是可以完美解决的,为了既保留Less的简便的变量写法,又解决变量无法修改的问题,因此利用字段替换编译的特性,我们可以将Less变量赋值为css变量,这样当编译之后所生成的css,依然是变量形式储存内容,具体代码可以参考:
colors.less
global.less
随后正常在main.js
引入global.less
即可:
问题延伸
问题到这里解决了吗?当然,但是还有个需求场景,某些网站会提供用户手动切换深色浅色模式的功能,而css变量可在运行中动态修改的优势就显现了出来
这里就需要js在运行中更改变量啦,具体的实现逻辑如下:
这里采用触发事件的方式进行,在Vue3中,你可以使用mitt
进行事件的监听,
可以直接注册在全局app上,也可以单独延续Vue2的习惯创建Vue实例挂载到上面:
这里的举例是创建Vue实例挂载到上面,新建一个eventBus.js
这样就可以全局触发和监听事件
接下来创建一个工具函数,在挂载时候添加监听,新建util/useColorScheme.js
这个就是在当触发themeChange事件,切换页面的颜色主题,在onMounted,onUnmounted生命周期钩子函数中设置,工具都准备好啦,就可以在任意地方使用啦
总结一下
其实有点复杂不太优雅,不过在大的Vue项目中,一定会用到pinia,mitt等工具来进行状态管理,全局事件总线监听的,折腾一下利于积累经验()
回到最开始的问题,原生css变量可用于动态修改,给了实时切换的可能,而less/scss的便捷写法又能大大简化开发,好啦,就到这里呀