Nuxt.js配置主题切换

介绍

Nuxt.js项目,设计了几种主题。点击选择的主题,页面样式对应切换

项目样式使用less编写

思路

  • 通过给body添加不同类名的方法,来切换。
  • 各个主题对应的颜色,配置在一个less文件中
  • less文件中定义一个方法,该方法可以循环生成所有的样式
  • 各组件的样式部分,使用此方法生成所有主题的样式

实现

以两种主题theme-greentheme-red为例

  • assets/less/目录下添加theme.less文件
@themes: theme-green, theme-red; @theme-green-mc: #4AD991; @theme-red-mc: red; .setTheme() { .loop(@i) when (@i < length(@themes)+1){ @theme: extract(@themes, @i); @mc: '@{theme}-mc'; body.@{theme}{ .theme(@@mc); } .loop(@i+1); } .loop(1); }
  • 组件中样式部分代码如下
@import '../../assets/less/theme.less'; .theme(@mc) { .gbanner{ position: relative; height: 564px; // ... .gbanner-d{ color: @mc; // ... } } // ... } .setTheme();
  • 修改nuxt.config.js文件,给body添加默认类theme-green
// ... module.exports = { // ... head: { // ... bodyAttrs: { class: 'theme-green' } }, // ... }
  • 切换主题部分代码
// ... export default { // ... methods: { // ... changeTheme(theme) { document.body.setAttribute('class', theme) } // ... } // ... } // ...

持久化

  • 持久化的话,需要将theme值存储到localstorage或者cookie
  • 页面初始化时,给body设置类名的方法暂时没有找到
  • 插件的方式或者在beforeMount或者mounted生命周期设置的话,页面刚加载的时候还是默认主题,然后突然变成设置的主题。效果不好
  • 这里换一下思路,给全部的layout最外层div设置类名
  • 这里还是以两种主题theme-greentheme-red为例
  • assets/less/目录下添加theme.less文件
@themes: theme-green, theme-red; @theme-green-mc: #4AD991; @theme-red-mc: red; .setTheme() { .loop(@i) when (@i < length(@themes)+1){ @theme: extract(@themes, @i); @mc: '@{theme}-mc'; // 这里有区别,body后面有一个空格 body .@{theme}{ .theme(@@mc); } .loop(@i+1); } .loop(1); }
  • 组件中样式部分代码不变。如下
@import '../../assets/less/theme.less'; .theme(@mc) { .gbanner{ position: relative; height: 564px; // ... .gbanner-d{ color: @mc; // ... } } // ... } .setTheme();
  • 修改nuxt.config.js文件,去掉添加的bodyAttrs
// ... module.exports = { // ... head: { // ... // bodyAttrs: { // class: 'theme-green' // } }, // ... }
  • 修改store/index.js文件,添加主题相关代码(nuxtServerInit相关设置参考:Nuxt.js常见问题
// ... import Cookies from 'js-cookie' // ... export const state = () => ({ themes: ['theme-green', 'theme-red'], theme: 'theme-green', // ... }) // ... export const mutations = { setTheme(state, theme) { if (state.themes.includes(theme)) { state.theme = theme Cookies.set('theme', theme) } }, // ... } export const actions = { nuxtServerInit({ commit }, { req }) { const cookie = req && req.headers.cookie if (cookie) { // 将cookie转成json对象(自己实现该方法) const cookieObj = cookieParse(cookie) const { theme } = cookieObj theme && commit('setTheme', theme) } }, // ... } // ...
  • 修改store/getters.js文件
const getters = { theme: state => state.theme, // ... } // ...
  • 在根目录下新建mixins/目录
  • mixins/目录下新建layout.js文件(除error.vue外的所有layout文件都mixin此文件)
import { mapGetters } from 'vuex' export default { computed: { ...mapGetters(['theme']) }, created() { if (process.browser) { this.$store.commit('setTheme', this.theme) } } }
  • 修改除error.vue外的所有layout文件
<template> <div class="layout-container" :class="theme"> <!-- 省略内容 --> </div> </template> <script> import layoutMixin from '@/mixins/layout' export default { mixins: [layoutMixin], // ... } </script>
  • 切换主题部分代码
// ... export default { // ... methods: { // ... changeTheme(theme) { this.$store.commit('setTheme', theme) } // ... } // ... } // ...

创作不易,若本文对你有帮助,欢迎打赏支持作者!

 分享给好友: