【Vue 开发实战】实战篇 # 42:如何定制主题及动态切换主题

简介: 【Vue 开发实战】实战篇 # 42:如何定制主题及动态切换主题

说明

【Vue 开发实战】学习笔记。



vuecli3 配置

fa79a115293a41e89d5cf9c4d6cac380.png

module.exports = {
    css: {
        loaderOptions: {
            less: {
                modifyVars: {
                    'primary-color': '#1DA57A',
                },
                javascriptEnabled: true
            },
        }
    },
}


4272e7ce1f0846fca29fce4db58ee340.png


我们可以修改一下写法

<style lang="less" src="./index.less"></style>


引入下面的 index.less 就行

@import "~ant-design-vue/lib/style/themes/default.less";
.kaimo-handle {
    position: absolute;
    top: 240px;
    right: 300px;
    width: 48px;
    height: 48px;
    background-color: @primary-color;
    color: #fff;
    font-size: 20px;
    text-align: center;
    line-height: 48px;
    border-radius: 3px 0 0 3px;
}


8a46f48edc1e41ee998ed9e49874cc5a.png


在线动态编译


如果你有报错可以参考我遇到的问题文章链接:Ant design vue动态主题切换报错Error LessError: Cannot find module ‘antd/lib/style/themes/default.less

这里我们使用 antd-theme-webpack-plugin

这个 webpack 插件用于生成特定颜色的 less/css 并注入到您的 index.html 文件中,以便您可以在浏览器中更改 Ant Design 特定的颜色主题。


具体的配置看文档就行。


但是这个我们不安装该依赖,主要原因还是版本1.3.9报错,有兴趣的可以看看我刚刚提到的文章。



1、新建插件

我们新建一个 ant-design-vue-pro\webpack-plugins\antd-theme-webpack-plugin.js 插件:里面的代码直接复制 antd-theme-webpack-plugin 的代码。

// https://github.com/mzohaibqc/antd-theme-webpack-plugin/blob/master/index.js
const { generateTheme } = require("antd-theme-generator");
const webpack = require("webpack");
const { RawSource } = webpack.sources || require("webpack-sources");
const path = require("path");
class AntDesignThemePlugin {
    constructor(options) {
        const defaultOptions = {
            varFile: path.join(__dirname, "../../src/styles/variables.less"),
            antDir: path.join(__dirname, "../../node_modules/antd"),
            stylesDir: path.join(__dirname, "../../src/styles/antd"),
            themeVariables: ["@primary-color"],
            indexFileName: "index.html",
            generateOnce: false,
            lessUrl: "https://cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js",
            publicPath: "",
        };
        this.options = Object.assign(defaultOptions, options);
        this.generated = false;
        this.version = webpack.version;
    }
    apply(compiler) {
        const pluginName = "AntDesignThemePlugin";
        if (this.version.startsWith("5.")) {
            compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
                compilation.hooks.processAssets.tapAsync(
                    {
                        name: pluginName,
                        stage: 
                            webpack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
                    },
                    (assets, callback) =>
                        this.addAssets(compilation, assets, callback)
                );
            });
        } else {
            compiler.hooks.emit.tapAsync(pluginName, (compilation, callback) =>
                this.addAssets(compilation, compilation.assets, callback)
            );
        }
    }
    addAssets(compilation, assets, callback) {
        this.generateIndexContent(assets, compilation);
        if (this.options.generateOnce && this.colors) {
            this.generateColorStylesheet(compilation, this.colors);
            return callback();
        }
        generateTheme(this.options)
            .then((css) => {
                if (this.options.generateOnce) {
                    this.colors = css;
                }
                this.generateColorStylesheet(compilation, css);
                callback();
            })
            .catch((err) => {
                callback(err);
            });
    }
    generateIndexContent(assets, compilation) {
        if (
            this.options.indexFileName &&
            this.options.indexFileName in assets
        ) {
            const index = assets[this.options.indexFileName];
            let content = index.source();
            if (!content.match(/\/color\.less/g)) {
                const less = `
                    <link rel="stylesheet/less" type="text/css" href="${this.options.publicPath}/color.less" />
                    <script>
                        window.less = {
                        async: false,
                        env: 'production'
                        };
                    </script>
                    <script type="text/javascript" src="${this.options.lessUrl}"></script>
                `;
                const updatedContent = content
                    .replace(less, "")
                    .replace(/<body>/gi, `<body>${less}`);
                if (this.version.startsWith("5.")) {
                    compilation.updateAsset(
                        this.options.indexFileName,
                        new RawSource(updatedContent),
                        { size: updatedContent.length }
                    );
                    return;
                }
                index.source = () => updatedContent;
                index.size = () => updatedContent.length;
            }
        }
    }
    generateColorStylesheet(compilation, source) {
        if (this.version.startsWith("5.")) {
            compilation.emitAsset("color.less", new RawSource(source), {
                size: source.length,
            });
            return;
        }
        compilation.assets["color.less"] = {
            source: () => source,
            size: () => source.length,
        };
    }
}
module.exports = AntDesignThemePlugin;



2、安装依赖

然后安装 antd-theme-webpack-plugin 需要的依赖 antd-theme-generator

此脚本生成颜色特定的样式/更少文件,您可以使用该文件在浏览器中动态更改主题

npm install antd-theme-generator@1.2.3 -D


具体可以看文档: https://github.com/mzohaibqc/antd-theme-generator



3、配置 vue.config.js

const path = require("path");
const AntDesignThemePlugin = require('./webpack-plugins/antd-theme-webpack-plugin');
const options = {
    antDir: path.join(__dirname, './node_modules/ant-design-vue'),
    stylesDir: path.join(__dirname, './src'),
    varFile: path.join(__dirname, './src/assets/styles/theme/variables.less'),
    themeVariables: ['@primary-color'],
    generateOnce: false
}
const themePlugin = new AntDesignThemePlugin(options);
module.exports = {
    lintOnSave: false,
    css: {
        loaderOptions: {
            less: {
                modifyVars: {
                    'primary-color': '#1DA57A',
                },
                javascriptEnabled: true
            },
        }
    },
    chainWebpack: config => {
        const svgRule = config.module.rule('svg');
        // 清除已有的所有 loader。
        // 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。
        svgRule.uses.clear();
        // 添加要替换的 loader
        svgRule.use('vue-svg-loader').loader('vue-svg-loader');
    },
    configureWebpack: {
        plugins: [ themePlugin ]
    },
    devServer: {
        proxy: {
            // '@(/api)': { target: 'http://localhost:3000',
            '/api': {
                target: 'http://localhost:8080',
                bypass: function (req, res, proxyOptions) {
                    if (req.headers.accept.indexOf('html') !== -1) {
                        console.log('Skipping proxy for browser request.');
                        return '/index.html';
                    } else if(process.env.MOCK !== "none") {
                        // 将请求url转为文件名
                        const name = req.path.split("/api/")[1].split("/").join("_");
                        const mock = require(`./mock/${name}`);
                        const result = mock(req.method);
                        // 需要清除缓存
                        delete require.cache[require.resolve(`./mock/${name}`)];
                        return res.send(result);
                    }
                },
            },
        },
    },
}


4、添加 variables.less

新建 ant-design-vue-pro\src\assets\styles\theme\variables.less

@import "~ant-design-vue/lib/style/themes/default.less";

关于 ~ 的使用可以查看:https://www.npmjs.com/package/less-loader#webpack-resolver



5、配置 index.html

<!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><%= htmlWebpackPlugin.options.title %></title>
    </head>
    <body>
        <noscript>
            <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
        </noscript>
        <div id="app"></div>
        <!-- built files will be auto injected -->
    <link rel="stylesheet/less" type="text/css" href="/color.less" />
    <script>
      window.less = {
        async: false,
        env: 'production',
                javascriptEnabled: true,
                modifyVars: {
                    'primary-color': 'orange',
                }
      };
    </script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js"></script>
    </body>
</html>


6、效果

启动服务,我们就可以看到:

e354ef30a6fd427db7a78b6b2a27c484.png

我们动态修改一下,在控制台将主题色改为粉色的,执行下面代码

window.less.modifyVars({"@primary-color": "pink"})

我们可以看到主题色就改变了。


103e357a25a74f8098008faf61e7002c.png


关于生成的 color.less 文件,可以访问 http://localhost:8080/color.less 查看

34344d2701084131b2b0a2e7494e15e5.png






目录
相关文章
|
3天前
|
监控 JavaScript 前端开发
使用Vue.js开发员工上网行为监控的实时数据展示页面
使用Vue.js开发的实时员工上网行为监控页面,展示员工访问的网站、应用和时间等数据。页面响应式设计,适应不同设备。通过Vue组件显示实时数据,如`&lt;li v-for=&quot;activity in activities&quot;&gt;`循环渲染。数据定时更新,利用Vue的生命周期钩子和axios从服务器获取并自动刷新,确保数据的时效性。该页面有助于管理者即时了解员工网络活动,保障企业网络安全和资源管理。
23 5
|
18小时前
|
JavaScript 前端开发 测试技术
使用 Vue CLI 脚手架生成 Vue 项目
通过 Vue CLI 创建 Vue 项目可以极大地提高开发效率。它不仅提供了一整套标准化的项目结构,还集成了常用的开发工具和配置,使得开发者可以专注于业务逻辑的实现,而不需要花费大量时间在项目配置上。
53 7
使用 Vue CLI 脚手架生成 Vue 项目
|
2天前
|
JavaScript 算法
“Error: error:0308010C:digital envelope routines::unsupported”启动vue项目遇到一个错误【已解决
“Error: error:0308010C:digital envelope routines::unsupported”启动vue项目遇到一个错误【已解决
8 1
|
2天前
|
JavaScript
error Component name “Login“ should always be multi-word vue/multi-word-component-names【已解决】
error Component name “Login“ should always be multi-word vue/multi-word-component-names【已解决】
6 1
|
2天前
|
JavaScript
vue知识点
vue知识点
10 3
|
3天前
|
JavaScript 前端开发 Java
【vue实战项目】通用管理系统:作业列表
【vue实战项目】通用管理系统:作业列表
16 0
|
10天前
|
JavaScript 前端开发 开发者
vue3+ts配置跨域报错问题解决:> newpro2@0.1.0 serve > vue-cli-service serve ERROR Invalid options in vue.
【6月更文挑战第3天】在 Vue CLI 项目中遇到 &quot;ERROR Invalid options in vue.config.js: ‘server’ is not allowed&quot; 错误是因为尝试在 `vue.config.js` 中使用不被支持的 `server` 选项。正确配置开发服务器(如代理)应使用 `devServer` 对象,例如设置代理到 `http://xxx.com/`: ```javascript module.exports = { devServer: {
24 1
|
3天前
|
JavaScript API
【vue实战项目】通用管理系统:信息列表,信息的编辑和删除
【vue实战项目】通用管理系统:信息列表,信息的编辑和删除
20 2
|
3天前
|
JavaScript API
【vue实战项目】通用管理系统:信息列表,信息录入
【vue实战项目】通用管理系统:信息列表,信息录入
11 3
|
3天前
|
JavaScript 前端开发 API
【vue实战项目】通用管理系统:学生列表
【vue实战项目】通用管理系统:学生列表
15 2