The ultimate goals of skin peels are as follows:

  1. A new set of themes can be developed with a simple configuration

  2. Multiple built-in skins

  3. You can set any color you want to generate a new theme CSS

Initialize a project vue-switch-theme using vue-cli.

The CSS preprocessing language selected here is less.

In general, the realization of multiple themes is to define a variety of theme-related variables in advance, such as theme color, text color, navigation background color and so on, and adjust variables for different themes. In order to quickly develop a new set of topics, ideally configure as few variables as possible. This leads to the following topic development process.

The theme directory structure is as follows:

  • Theme /blue/style.less: Blue theme entry style

  • Theme /dark/style.less: Dark theme entry style

  • Theme /default/style.less: the default theme entry style

  • The theme/template/style. Less: template theme, a new theme for real-time configuration

  • Theme /style.less: Summarize all the styles in the system

  • Theme /var.less: Global theme less variable

Theme /style.less is generally used to summarize all styles in a project. Such as:

@import '.. /css/components/select-city.less'; @import '.. /css/components/calendar.less'; @import '.. /css/views/home.less'; @import '.. /css/views/about.less';Copy the code

The global theme LESS variable file contains variables for the default theme, as well as variables that are independent of the theme. Such as:

@calendar-bg-color: #f1f1f1;

@main-font-color: #444;
@tip-font-color: #999;

@nav-width: 200px;
Copy the code

The content structure of each theme less file is as follows, and the order cannot be changed arbitrarily:

// Import the global topic variable @import '.. /var.less'; @primary-color: #008891; // Import system style collection @import '.. /style.less';Copy the code

Here we will focus on how to do the style.less file under template. This template as the name implies is a template theme, and eventually generate a template theme CSS file.

Template /style.less Defines all theme-related variables as placeholders to facilitate string substitutions. Such as:

// Import the global topic variable @import '.. /var.less'; // override theme variable configuration @primary-color: '__primary-color__'; @main-font-color: '__main-font-color__'; @tip-font-color: '__tip-font-color__'; // Import system style collection @import '.. /style.less';Copy the code

That’s it for topic development. Here’s how to configure the packaging. As you can see from the directory structure of the theme development above, each theme eventually generates a CSS file. There are several ways to do this:

  1. Styles are packaged separately from projects (i.e. Vue-cli-service serve/build). For example, lessC is used for packaging, but the images, fonts and other resources used in less need to be handled by ourselves

  2. Package along with the project, but Webpack also does not support directly configuring a solution like multiple themes, so we have to configure multiple entry projects to solve this problem.

Configure each topic entry in vue.config.js.

module.exports = { filenameHashing: false, chainWebpack: (config) = > {/ / theme entry does not need to generate HTML config. Plugins. The store. Delete (' HTML - theme_blue) config.plugins.store.delete('html-theme_dark') config.plugins.store.delete('html-theme_template') }, pages: { index: { entry: 'src/main.js', }, theme_blue: { entry: 'src/assets/theme/blue/style.less', }, theme_dark: { entry: 'src/assets/theme/dark/style.less', }, theme_template: { entry: 'src/assets/theme/template/style.less', }, }, }Copy the code

The default theme is introduced in main.js, so there is no need to configure the entry separately. The final packaged file is shown in the following figure.

If you open theme_template. CSS, theme-related variables are replaced with placeholders. Note that you need to replace the placeholders as well as the quotation marks.

To switch skins, you simply load the CSS file for the skin.

For example, loading different skins on the PHP back end via URL arguments.

<? php if(\Yii::$app->request->get('theme') =='dark'){? > <link rel="stylesheet" href="/css/theme_dark.css"> <? php }else{? > <link rel="stylesheet" href="/css/index.css"> <? php }? >Copy the code

Or load different skins directly in JavaScript.

const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = '/css/theme_dark.css'
document.head.appendChild(link)
Copy the code

How to set the variables related to the theme and generate a new theme CSS file?

The simplest way:

  1. The variables related to the topic can be refined to make a configuration page for users to configure

  2. After the configuration is complete, submit it to the backend to generate a CSS file

URL argument:

  1. Convert the theme configuration JSON to base64 and place it in a URL parameter, such as theme= XXX

  2. The backend generates MD5 values from Base64, parses them into theme configurations, and generates new CSS files

  3. The file name is the MD5 value generated in the second step. The advantage of this is that the same theme configuration does not need to be generated repeatedly. In actual production, the updating time of the template theme CSS file should also be considered.

FilenameHashing was disabled to keep the built-in theme file names fixed. This is definitely not appropriate in real production, so we need to change the hash to the URL parameter. Adjust filename and chunkfileName in vue.config.js.

chainWebpack: (config) => { if (process.env.NODE_ENV === 'production') { config.output.filename('js/[name].js? [contenthash:8]') config.output.chunkFilename('js/[name].js? [contenthash:8]') config.plugin('extract-css').tap((args) => { args[0].filename = 'css/[name].css? [contenthash:8]' args[0].chunkFilename = 'css/[name].css? [contenthash:8]' return args }) } }Copy the code

Welcome to pay attention to the front public number [front track].