怎么做一个前端在线主题切换? 这个套路让我瞬间想起了 Ant Design, Ant Desgin 就有一个这样的功能,于是去看了官方文档。
![](https://img.haomeiwen.com/i10041071/940227bddb9a67ad.png)
文档上说的是利用 less 的 modifyVars 进行变量的覆写来实现的,于是我又去查了下less的文档, less.js
会读取到rel="stylesheet/less"
的 link 的内容, 调用less.modifyVars
会重新对读取到的内容进行编译,并且最终通过添加 <style></style>
的形式, 覆盖掉之前的样式。
既然知道了这个原理,那我们需要想一下怎么利用less
的这个特性实现页面主题色切换。
- 首先我们需要一个 less 变量来定义当前的主题色,
@theme-color: black;
- 然后我们需要一个 less.js 来进行 modifyVars 的操作以及 less 文件的引入
<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="less.js" type="text/javascript"></script>
- 最后我们只需要去写一个改变当前主题色的方法
function changeTheme() {
window.less.modifyVars({
"@theme-color": "red"
});
}
好了, 上面就是我们的思路, 梳理好之后, 我们就要思考怎么和项目结合在一起
-
less 的变量问题,其实相对来讲我们的项目中并不只会有一个
@theme-color
这种变量,这里面我们可能会有十多个变量, 包括我们可以去定义下全局的字体、字体大小,我们需要根据项目的特性进行划分 -
我们怎么去把框架中的 less 抽到我们打包后的 dist 文件中, 这里我推荐的做法是通过file-loader来做,配置如下
// 我们需要在less-loader里将我们不要打包的less exclude掉
// 本例中不需要打包的less为 styles.less
{
test: /\.less$/,
use: "less-loader",
exclude: /styles\.less/
},
// 然后利用file-loader 将styles.less打包到我们项目的根目录
// 如果不放在根目录下,可以根据实际情况进行配置
{
test: /\.less$/,
loader: "file-loader",
options: {
name: "[name].[ext]" // 默认的话 会将name hash掉
}
include: /styles\.less/
}
我们在项目中引用的话,就可以直接通过一下形式进行引用
<link rel="stylesheet/less" type="text/css" href="styles.less" />
- less.js
一般来说,我们可以直接通过在 html 里面加 script 标签的形式来做,但是我们需要考虑的是并不是每一个用户进来都会用主题换色这样一个功能,所以我们可以利用 webpack 的lazy load来做些小优化。
async function loadLess(option) {
// 如果之前已经加载就不再重复加载, 直接返回less
if (!window.less) {
// 通过先定义less 来注入option 参考 lesscss.org
window.less = option;
return await import("less")
} else {
return window.less
}
}
最后思考,如果我们下次遇到一个需求是说把全站的button的颜色都要直接在线变色,其实这就是一个前期架构的问题了,如果我们能在项目早期去做一些样式的抽象和管理,对于后续我们去实现这样一些需求,我们就不再头疼了,我们可以基于less的这种方式,去做一些整站的样式管理,项目也会更加清晰 易于修改.
网友评论