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


    说明

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

    vuecli3 配置

    在这里插入图片描述

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

    在这里插入图片描述

    我们可以修改一下写法

    <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;
    }
    

    在这里插入图片描述

    在线动态编译

    如果你有报错可以参考我遇到的问题文章链接: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 = `
                        ${this.options.publicPath}/color.less" />
                        
                        
                    `;
    
                    const updatedContent = content
                        .replace(less, "")
                        .replace(//gi, `${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>
            
    		<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、效果

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

    在这里插入图片描述

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

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

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

    在这里插入图片描述

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

    在这里插入图片描述

  • 相关阅读:
    【c++】——类和对象(下) 万字解答疑惑
    第六十章 IIS 7 或更高版本的替代选项 (Windows) - 替代选项 3:将 ISAPI 模块与 NSD (CSPcms.dll) 一起使用
    【历史上的今天】9 月 22 日:2017 年图灵奖得主诞生;计算机软件知识产权保护案;施乐公司的自我毁灭
    【微服务】- 服务调用 - OpenFeign
    读写分离的利器——MySQL Proxy
    大数据docker部署
    金仓数据库 KingbaseES 插件参考手册 S (2)
    嵌入式开发:在工业应用程序中优化GUI的5个技巧
    Js中常见的数据结构(Data Structure)
    PIGOSS BSM 监控系统采集方式Agent 3.0技术与使用简介
  • 原文地址:https://blog.csdn.net/kaimo313/article/details/126704433