【Vue,Vuex】为你的vue项目添加vuex支持,并实现全局动态主题颜色修改

若依VUE前后端分离项目动态主题切换实战指南 本文详细介绍了若依VUE前后端分离项目中实现动态主题切换的实战方法。通过SCSS变量修改和组件调整,开发者可以轻松实现类似Element UI的多主题切换效果,包括深色、蓝色等自定义配色方案。文章重点讲解了导航栏、侧边栏的样式改造,主题配色方案设计,以及高级技巧如SVG图标处理和移动端适配,帮助开发者打造更灵活的前端界面。 阅读详情

重要声明:本文章仅仅代表了作者个人对此观点的理解和表述。读者请查阅时持自己的意见进行讨论。

本文原文:【Vue,Vuex】为你的vue项目添加vuex支持,并实现全局动态主题颜色修改。本文更新不及时建议到原文地址浏览。

为了让读者更加容易理解并快速掌握相关知识点,本文将从项目的创建开始进行内容的介绍。本文使用@vue/cli 3.x工具来创建vue项目,这是笔者在撰写本文时的版本。对于此工具的安装,点击这里 查看详细信息。

本文通过改变主题色来讲解vuex的使用,篇幅上可能vuex不是很多,你可以使用目录直接查看vuex部分,也可以根着内容实现效果。本文的主题效果不是最佳解决方案,只为效果演示,读者了解原理后需自己考究实用性,并加以自身优化。

一、创建项目

通过 cli 工具,可直接使用命令创建项目,本项目名为 vuex-theme , 那么使用命令:

 vue create vuex-theme

就可以很方便的创建好项目了。项目创建好之后,就可以先来一波测试运行,进入创建好的项目目录 vuex-theme, 打开命令窗口,运行命令 npm run serve 即可开启测试服务,在浏览器输入提示的地址即可看到初始项目的运行结果,如下所示:

图1

看到了效果还不够,接下来再看看项目的目录结构:

图2

为了不让初始项目内容对本文介绍的内容产生影响,先将自动生成的文件内容进行清理。

首先清理App.vue,删除里面的多余内容,最终效果:

<!-- App.vue -->
<template>
  <div id="app">

  </div>
</template>

<script>

export default {
  name: 'app',
  components: {}
}
</script>

然后清理 HelloWorld.vue 文件,此文件直接删除,不需要它。再将 assets 目录下的 logo.png 删除,我们也不需要它。

二、加入路由支持

默认创建的项目没有自动加入路由支持,一个单页面前端应用,既然咱们要配合vuex实现主题色切换,那必然会是多界面的,就必然需要路由帮我们导航多页面支持了。

1、安装 vue-router

使用命令 npm install vue-router --save-dev 即可完成安装。使用 --save-dev 参数,可将依赖保存到 package.json 文件,别人down了你的项目才不会把依赖落下。

2、路由代码加入

安装完成之后,便可以开始编写路由代码了。考虑到本案例虽然将会使用路由导航多个页面,但不会是很多页面。因此路由表就全部写在 main.js 里,如果自己的项目路由表较多,建议分出为一个独立的路由管理文件。打开 main.js 文件,修改内容为:

// main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'

Vue.config.productionTip = false
Vue.use(VueRouter)

// 这个数组目前还没有内容,因为还没有添加任何界面。
const routes = [];

new Vue({
  render: h => h(App),
  router: new VueRouter({
    routes: routes
  }),
}).$mount('#app')

继续打开文件 App.vue ,修改内容为:

<!-- App.vue -->
<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>

export default {
  name: 'app',
  components: {}
}
</script>

代码中添加了 router-view 组件,通过它就可以实现将 main.js 里路由数组里面的页面动态渲染到界面上。这两处代码修改完成了之后,就相当于完成了路由的加入。接下来的事情就是添加各个界面了。

三、基本功能实现 - todo事项

为了能有一个不错的功能实现,笔者选用了 TODO事项 这个知名而又小巧的功能需求作为演示。考虑到此程序将实现主题色的更换,所以,在代码实现上要兼顾颜色字段的设计,即便现在还没有加入vuex的使用,也要为后期留下可操作的途径。

1、建立默认配置文件

在项目src目录下新建一个 pageCfg.js 文件,此文件作文页面颜色配置文件,在没有任何颜色设置时,此文件可作为默认颜色配置文件。文件内容如下:

// pageCfg.js
export default {
    pageBackgroundColor: '#FFFFFF', // 页面背景色
    primaryColor:        '#1E9FFF', // 主要点缀颜色
    textPrimaryColor:    '#000000', // 主要文本颜色
    textSecondColor:     'gray',    // 次要文本颜色
}

然后修改 main.js 文件,引入配置,将其挂载到 Vue 的 prototype 上,这样方便每一个页面都能读取到配置内容:

// main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import PageCfg from './pageCfg'

Vue.config.productionTip = false
Vue.use(VueRouter)

// 将配置挂载到 prototype 上。
Vue.prototype.pageCfg = PageCfg;

// 这个数组目前还没有内容,因为还没有添加任何界面。
const routes = [];

new Vue({
  render: h => h(App),
  router: new VueRouter({
    routes: routes
  }),
}).$mount('#app')

2、添加用户登录页

todo事项,每个人都有自己要做的事情,所以每一个todo事项列表都必须先确定一个用户,因此专门为用户登入实现一个界面,在项目目录 src 下新建目录 pages 用于保存各个不同的界面。在pages下新建文件 login.vue 实现用户登录功能,这里简单的只需要提供一个用户名即可:

<!-- login.vue -->
<template>
    <div>
        <!-- 登录输入框 -->
        <div style="margin: 15px">
            <input placeholder="请输入你的用户名" v-model="user"/>
            &nbsp;<button @click="onLoginClick" :style="getBtnThemeColor()">登录</button>
        </div>
    </div>
</template>

<script>
    export default {
        methods: {

            // 登录按钮点击
            onLoginClick () {
                if (!this.user) return

                // 在 pageCfg 对象上为此用户分配一个存储数据的对象。
                this.pageCfg[this.user] = this.pageCfg[this.user] || [];

                // 转到首页
                this.$router.replace({
                    path: "/",
                    query: {
                        user: this.user
                    }
                });
            },

            // 获取配置的主题颜色。设置给按钮。
            getBtnThemeColor () {
                return {
                    color:           '#FFFFFF',
                    backgroundColor: this.pageCfg.primaryColor,
                    borderColor:     this.pageCfg.primaryColor
                }
            }
        },
        data () {
            return {
                user: ''
            }
        }
    }
</script>

代码中记录了用户名称,保存在 user 字段,用户必须输入一个值才能下一步。当用户输入值下一步时,会在 pageCfg 对象上为该用户分配一个存储数据的空间,该用户的所有数据就都会保存在这个空间里。然后会引导用户进入todo事项列表页,并将该用户的名称传递到下一个界面。

同时,为了迎合主题切换达到效果,特意为按钮加入了 getBtnThemeColor 方法,此方法返回配置的颜色数据,设置给按钮,这样按钮就可以通过配置修改颜色了。

3、添加todo事项列表页

用户进入todo事项列表界面时,就应该展示出用户的所有数据,并且提供一个新增数据的方式,因此使用如下代码实现基本功能:

// todo.vue
<template>
    <div>

        <!-- 根据配置文本主色改变此标题颜色 -->
        <h1 :style="getTxtPriMaryColor()">
            todo事项&nbsp;
            <button @click="onExitClick" :style="getBtnThemeColor()">退出</button>
        </h1>
        <ul>

            <!-- 根据配置文本主色改变此标题颜色 -->
            <li v-for="item in todo" :key="item.key" :style="getTxtPriMaryColor()">
                {{item.txt}}

                <!-- 根据配置文本次要色改变此事项颜色 -->
                <small :style="getTxtSecondColor()">{{item.date.toLocaleString()}}</small>
            </li>
            <li>
                <input ref="newTodoInput" placeholder="输入新事项内容"/>&nbsp;
                <button @click="onAddNewClick" :style="getBtnThemeColor()">添加新事项</button>
            </li>
        </ul>
    </div>
</template>

<script>
    export default {
        created () {
            this.user = this.$route.query.user
            this.todo = this.pageCfg[this.user]

            if (!this.user || !this.todo) {
                this.$router.replace("/login")
                return
            }
        },
        methods: {
            onAddNewClick () {
                let txt = this.$refs.newTodoInput.value
                if (!txt) return

                this.todo.push({
                    key: String(Date.now()),
                    txt: txt,
                    date: new Date()
                });
                this.$refs.newTodoInput.value = ''
            },
            onExitClick () {
                this.$router.replace("/login")
            },

            // 获取页面文本主颜色
            getTxtPriMaryColor () {
                return {
                    color: this.pageCfg.textPrimaryColor
                }
            },

            // 获取文本次要颜色
            getTxtSecondColor () {
                return {
                    color: this.pageCfg.textSecondColor
                }
            },

            // 获取配置的主题颜色。设置给按钮。
            getBtnThemeColor () {
                return {
                    color:           '#FFFFFF',
                    backgroundColor: this.pageCfg.primaryColor,
                    borderColor:     this.pageCfg.primaryColor
                }
            }
        },
        data () {
            return {
                user: '',
                todo: []
            }
        }
    }
</script>

可以看到,代码中首先读取传递进入的用户名,然后根据用户名将本页的列表数据进行初始化,这样页面即可对应显示出来。同时针对页面上的按钮,也同样提供了主题色设置方法。以及h1标题、li列表事项等,都加入了主题色配置获取方法。为了更明确的展示出颜色的应用方法,我并没有将按钮提取为一个公共组件,当然在读者实际开发中有需要的话,建议将共同操作都提取为一个组件去实现。然后本页提供了一个输入框,用户可以随时新增事项。

4、页面放入路由

现在我们把页面完成了,可将这两个页面放入路由映射表了。修改 main.js 内容如下:

// main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import PageCfg from './pageCfg'

Vue.config.productionTip = false
Vue.use(VueRouter)

// 将配置挂载到 prototype 上。
Vue.prototype.pageCfg = PageCfg;

// 加入写好的页面。 这里是使用了懒加载的方式。
const routes = [
    {path: "/login", component: () => import('./pages/login')},
    {path: "/",      component: () => import('./pages/todo')}
];

new Vue({
  render: h => h(App),
  router: new VueRouter({
    routes: routes
  }),
}).$mount('#app')

5、加入基本样式

为了让vue文件代码篇幅较小,我将一些样式写在了html文件中,打开项目目录public文件夹,编辑 index.html 文件,在其head内添加如下代码:

<style>
  span,i,input,button,small,strong,b,img {
    vertical-align: middle;
  }

  button {
    display: inline-block;
    border: 1px solid #d9d9d9;
    padding: 6px 10px;
    cursor: pointer;
  }
  input {
    padding: 6px 8px;
    outline: none;
  }
</style>
6、预览初形

当上面几步完成后,再次运行npm run serve开启测试,输入提示的地址,即可看到效果,这只是一个简单的示列,仅仅支持显示和新增,并且刷新页面将会导致数据全部丢失。效果如下:

图3

1、尝试修改主题

看起来还不错,至少没出什么大问题。现在我们尝试更改一下主题,我们的修改并不是直接在 pageCfg.js 文件里把配置给修改了,而是在 main.js 里,将 pageCfg.js 的值进行修改,从而达到目的,修改如下:

// main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import PageCfg from './pageCfg'

Vue.config.productionTip = false
Vue.use(VueRouter)

// 将配置挂载到 prototype 上。
Vue.prototype.pageCfg = PageCfg;

Vue.prototype.pageCfg.primaryColor     = "red";  // 将点缀主色修改为红色。
Vue.prototype.pageCfg.textPrimaryColor = "blue"; // 将文本主色修改为蓝色。

const routes = [
    {path: "/login", component: () => import('./pages/login')},
    {path: "/",      component: () => import('./pages/todo')}
];

new Vue({
  render: h => h(App),
  router: new VueRouter({
    routes: routes
  }),
}).$mount('#app')

我们将点缀主色修改为红色。将文本主色修改为蓝色。再次运行,发现已经生效了:

图4

2、适配背景

上面的一系列主题色的应用都只是将显示主色修改了,但背景一直都是白色,实际上到目前为止配置的背景色都没有应用起来。现在将其使用起来。由于背景只需要设置给网页背景,document.body 是一个不做的设置位置,但是该在哪个界面完整设置背景色这个任务?似乎在任何一个页面里实现这样的逻辑都显得有点不合理,那不如将代码放在 main.js 的 new Vue 的代码逻辑里面。修改 main.js 的代码:

// main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import PageCfg from './pageCfg'

Vue.config.productionTip = false
Vue.use(VueRouter)
Vue.prototype.pageCfg = PageCfg;

Vue.prototype.pageCfg.primaryColor     = "red";  // 将点缀主色修改为红色。
Vue.prototype.pageCfg.textPrimaryColor = "blue"; // 将文本主色修改为蓝色。

const routes = [
    {path: "/login", component: () => import('./pages/login')},
    {path: "/",      component: () => import('./pages/todo')}
];

new Vue({
    created() {

        // 页面初始时就设置一下页面背景色。
        document.body.style.backgroundColor = this.bgColor
    },
    render: h => h(App),
    router: new VueRouter({
        routes: routes
    }),
    watch: {

        // 监听这个颜色的改变,实现背景动态修改。
        bgColor(newvalue) {
            document.body.style.backgroundColor = newvalue
        }
    },
    data() {
        return {

            // 将背景色赋值给根vue对象的数据区块里。
            bgColor: this.pageCfg.pageBackgroundColor
        }
    }
}).$mount('#app')

现在,适配完成,但是看不到任何效果,因为咱们配置的背景颜色也是白色的,所有没有发生改变。这时如果再次修改颜色的值,并且添加一些新的颜色修改,就可以实现各种主题效果,现在实现一个夜间效果模式,修改颜色如下:

// main.js
import ...

...

Vue.prototype.pageCfg.pageBackgroundColor     = "#02010c"
Vue.prototype.pageCfg.primaryColor            = "#6e6e6e"
Vue.prototype.pageCfg.textPrimaryColor        = "#ffffff"
Vue.prototype.pageCfg.textSecondColor         = "#858585"

const routes = [...]

new Vue(...)

再次运行程序,发现效果已经有了:

图5

四、加入Vuex

目前看来,每次主题更换时,我们都需要去修改一下代码,然后重新运行(你可能感觉并没有重新运行,只是速度比较,快你感觉就是没有重新启动一样)才能看到效果。如何能做到不用修改代码,直接程序运行时,去修改状态值,并且让效果立即展示出来。当然有办法,

Vuex的加入就可以瞬间解决这个问题。vuex的作用是状态保持。可能不好理解,做一个比较你就明白了。每一个vue页面里,有一个data区域,这里面的数据和页面模板里面进行了绑定,你修改data的数据,页面就可以同时进行修改。那么这个data相当于就为这个页面做了状态保持。同样道理,vuex的作用就不仅是某个界面了,而是扩大到了整个vue应用内。

1、安装 vuex

和安装 vue-router 类似,使用命令 npm install vuex --save-dev 即可进行安装。安装完成后便可以在代码里进行使用了。

使用方式也和 vue-router 类似,直接创建对象然后注入根vue实例里。修改 main.js 文件,引入vuex(部分代码已隐藏):

// main.js
// ...
import Vuex from 'vuex'

// ...
Vue.use(Vuex);

// 直接创建对象
const store = new Vuex.Store({
    state: {},
    mutations: {}
});

new Vue({
    created() {...},
    render: h => h(App),
    router: new VueRouter({
        routes: routes
    }),
    watch: {...},
    data() {...},
    store: store // 将上面创建的store对象注入根vue实例
}).$mount('#app')

上面的代码就算是将vuex加入到了咱们的程序里,但还没有具体实现任何功能。可能你对此已经产生了一些疑惑。state 和 mutations 是拿来干嘛的?

思考一下,在每个页面的data数据区域里的数据,要修改它们时,是不是通常都是由页面里的 method 提供的某方法,或者对应生命周期方法里,但都离不开对应的页面。同样的道理,在这个为整个应用提供数据的store区域里如果没有一个统一的操作数据的地方,那岂不乱套了。各个页面都有各自的数据要处理,这个全局数据还搅和在里面岂不更加混乱。所以,store对象有一个固有的格式。其包含了一个 state 数据具体存放的对象、以及一个 mutations。所有操作state数据的方法写在mutations里面。代码最后通过 store 字段将其注入 vue根实例里面,这样你就可以在每个页面通过this.$store拿到store实例了。

现在有了这个基础,就可以继续完善 store 创建部分的代码,加入主题色相关的字段:

// main.js - 部分代码
const store = new Vuex.Store({
    state: {
        // 初始值就都使用配置的默认值。
        pageBackgroundColor: Vue.prototype.pageCfg.pageBackgroundColor,
        primaryColor:        Vue.prototype.pageCfg.primaryColor,
        textPrimaryColor:    Vue.prototype.pageCfg.textPrimaryColor,
        textSecondColor:     Vue.prototype.pageCfg.textSecondColor
    },
    mutations: {
        updateColor(state, payload) {
            state[payload.key] = payload.value
        }
    }
});

可以看到,我们为 state 添加了一些颜色字段。为 mutations 添加了一个更新颜色的方法。这个方法有两个参数,一个state,和一个payload,payload就是更新数据时传递进来的参数。

那么如何在页面里使用这个 updateColor 方法呢? 其实你无法直接使用到这个方法,vuex的store提供了一个commit方法,这个方法可以让你执行到 updateColor 方法,例如在某个页面里,想要更新页面背景色,就可以通过 this.$store.commit('updateColor', {key: 'pageBackgroundColor', value: 'pink'}), 从而将state里的pageBackgroundColor字段进行修改,也就达到了修改背景为粉色的效果了。

2、实现动态更改主题颜色

上一节已经了解了vuex的用法和相关代码的实现。现在可以将每个页面的与获取颜色有关的方法进行一些修改,好适配主题色的动态变化。

1)、全局背景适配

全局背景色的应用我们在第三节里写在了 main.js 里,因此,继续修改main.js文件。我们使用vuex加入后,就可以不用复杂的在main.js里绕这么多代码了,去除一些代码,然后使用store的subscribe实现每次修改主题颜色后就尝试修改背景:

// main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import PageCfg from './pageCfg'
import Vuex from 'vuex'

Vue.config.productionTip = false
Vue.use(VueRouter)
Vue.use(Vuex)
Vue.prototype.pageCfg = PageCfg;

Vue.prototype.pageCfg.pageBackgroundColor     = "#02010c";  // 修改默认背景色。
Vue.prototype.pageCfg.primaryColor            = "#6e6e6e";  // 将点缀主色修改为红色。
Vue.prototype.pageCfg.textPrimaryColor        = "#ffffff";  // 将文本主色修改为蓝色。
Vue.prototype.pageCfg.textSecondColor         = "#858585";  // 将文本主色修改为蓝色。

const routes = [
    {path: "/login", component: () => import('./pages/login')},
    {path: "/",      component: () => import('./pages/todo')}
];

// 直接创建对象就好了
const store = new Vuex.Store({
    state: {
        // 初始值就都是用配置的默认值。
        pageBackgroundColor: Vue.prototype.pageCfg.pageBackgroundColor,
        primaryColor:        Vue.prototype.pageCfg.primaryColor,
        textPrimaryColor:    Vue.prototype.pageCfg.textPrimaryColor,
        textSecondColor:     Vue.prototype.pageCfg.textSecondColor
    },
    mutations: {
        updateColor(state, payload) {
            state[payload.key] = payload.value
        }
    }
})

store.subscribe((mutation, state) => {
    // 每次修改state值之后,这里都会执行,不如就在这里设定背景色。
    document.body.style.backgroundColor = state.pageBackgroundColor
})

new Vue({
    render: h => h(App),
    router: new VueRouter({
        routes: routes
    }),
    store: store
}).$mount('#app')

上述代码中,使用 subscribe 订阅了state的修改事件,每次修改都会调用传入的方法,如果改了背景色,自然就会自动修改背景。

2)、登录页颜色适配

现在修改登录页面,使其适配vuex的加入:

login.vue
<template>
    <div>
        <!-- 登录输入框 -->
        <div style="margin: 15px">
            <input placeholder="请输入你的用户名" v-model="user"/>
            &nbsp;<button @click="onLoginClick" :style="getBtnThemeColor">登录</button>
        </div>
    </div>
</template>

<script>
    export default {
        methods: {

            // 登录按钮点击
            onLoginClick () {
                if (!this.user) return

                // 在 pageCfg 对象上为此用户分配一个存储数据的对象。
                this.pageCfg[this.user] = this.pageCfg[this.user] || [];

                // 转到首页
                this.$router.replace({
                    path: "/",
                    query: {
                        user: this.user
                    }
                });
            }
        },
        computed: {
            // 获取配置的主题颜色。设置给按钮。
            getBtnThemeColor () {
                return {
                    color:           '#FFFFFF',
                    backgroundColor: this.$store.state.primaryColor,
                    borderColor:     this.$store.state.primaryColor
                }
            }
        },
        data () {
            return {
                user: ''
            }
        }
    }
</script>

可以看到,在模板代码区,按钮的style将原来后面的括号移除了,js代码区,将原本在methods里面的getBtnThemeColor方法移动到了computed里面,并在getBtnThemeColor方法里面修改为使用store提供的数据。

3)、事项列表页颜色适配

适配方法和登录页相似,去除布局代码里的方法括号,将方法移动到computed里面,并修改一下数据来源,即可完成:

todo.vue
<template>
    <div>

        <!-- 根据配置文本主色改变此标题颜色 -->
        <h1 :style="getTxtPriMaryColor">
            todo事项&nbsp;
            <button @click="onExitClick" :style="getBtnThemeColor">退出</button>
        </h1>
        <ul>

            <!-- 根据配置文本主色改变此标题颜色 -->
            <li v-for="item in todo" :key="item.key" :style="getTxtPriMaryColor">
                {{item.txt}}

                <!-- 根据配置文本次要色改变此事项颜色 -->
                <small :style="getTxtSecondColor">{{item.date.toLocaleString()}}</small>
            </li>
            <li>
                <input ref="newTodoInput" placeholder="输入新事项内容"/>&nbsp;
                <button @click="onAddNewClick" :style="getBtnThemeColor">添加新事项</button>
            </li>
        </ul>
    </div>
</template>

<script>
    export default {
        created () {
            this.user = this.$route.query.user
            this.todo = this.pageCfg[this.user]

            if (!this.user || !this.todo) {
                this.$router.replace("/login")
                return
            }
        },
        methods: {
            onAddNewClick () {
                let txt = this.$refs.newTodoInput.value
                if (!txt) return

                this.todo.push({
                    key: String(Date.now()),
                    txt: txt,
                    date: new Date()
                });
                this.$refs.newTodoInput.value = ''
            },
            onExitClick () {
                this.$router.replace("/login")
            }
        },
        computed: {

            // 获取页面文本主颜色
            getTxtPriMaryColor () {
                return {
                    color: this.$store.state.textPrimaryColor
                }
            },

            // 获取文本次要颜色
            getTxtSecondColor () {
                return {
                    color: this.$store.state.textSecondColor
                }
            },

            // 获取配置的主题颜色。设置给按钮。
            getBtnThemeColor () {
                return {
                    color:           '#FFFFFF',
                    backgroundColor: this.$store.state.primaryColor,
                    borderColor:     this.$store.state.primaryColor
                }
            }
        },
        data () {
            return {
                user: '',
                todo: []
            }
        }
    }
</script>
4)、查看效果

现在我们再次运行,就可以看到通过vuex加入后的主题效果,所实话,和没加vuex前完全一致。。。由于我们没有再次修改颜色值,所以颜色一直保持夜间主题模式。效果就不用再展示了,和之前一样的。

5)、加入颜色动态修改

为了更好的展示效果,将在todo事项列表页添加四个颜色修改视图,这样可以非常直观的看到vuex发挥的作用。开源组件 vue-color 就帮我们完成了这样一个控件,通过它就可以方便的实现颜色选择。
第一步先安装它 npm install vue-color --save-dev。然后就可以在页面中使用了,修改todo.vue代码如下:

// todo.vue
<template>
    <div>

        <!-- 根据配置文本主色改变此标题颜色 -->
        <h1 :style="getTxtPriMaryColor">
            todo事项&nbsp;
            <button @click="onExitClick" :style="getBtnThemeColor">退出</button>
        </h1>
        <ul>

            <!-- 根据配置文本主色改变此标题颜色 -->
            <li v-for="item in todo" :key="item.key" :style="getTxtPriMaryColor">
                {{item.txt}}

                <!-- 根据配置文本次要色改变此事项颜色 -->
                <small :style="getTxtSecondColor">{{item.date.toLocaleString()}}</small>
            </li>
            <li>
                <input ref="newTodoInput" placeholder="输入新事项内容"/>&nbsp;
                <button @click="onAddNewClick" :style="getBtnThemeColor">添加新事项</button>
            </li>
        </ul>

        <div style="margin-top: 15px">
            <div style="display: inline-block">
                <span :style="getTxtPriMaryColor">背景</span>
                <ChromeColorPicker v-model="pageBackgroundColor"/>
            </div>&nbsp;
            <div style="display: inline-block">
                <span :style="getTxtPriMaryColor">主色</span>
                <ChromeColorPicker v-model="primaryColor"/>
            </div>&nbsp;
            <div style="display: inline-block">
                <span :style="getTxtPriMaryColor">文本主色</span>
                <ChromeColorPicker v-model="textPrimaryColor"/>
            </div>&nbsp;
            <div style="display: inline-block">
                <span :style="getTxtPriMaryColor">文本次色</span>
                <ChromeColorPicker v-model="textSecondColor"/>
            </div>
        </div>
    </div>
</template>

<script>
    import { Chrome } from 'vue-color'

    export default {
        components: {
            ChromeColorPicker: Chrome
        },
        created () {
            this.user = this.$route.query.user
            this.todo = this.pageCfg[this.user]

            if (!this.user || !this.todo) {
                this.$router.replace("/login")
                return
            }
        },
        methods: {
            onAddNewClick () {
                let txt = this.$refs.newTodoInput.value
                if (!txt) return

                this.todo.push({
                    key: String(Date.now()),
                    txt: txt,
                    date: new Date()
                });
                this.$refs.newTodoInput.value = ''
            },
            onExitClick () {
                this.$router.replace("/login")
            }
        },
        computed: {

            // 获取页面文本主颜色
            getTxtPriMaryColor () {
                return {
                    color: this.$store.state.textPrimaryColor
                }
            },

            // 获取文本次要颜色
            getTxtSecondColor () {
                return {
                    color: this.$store.state.textSecondColor
                }
            },

            // 获取配置的主题颜色。设置给按钮。
            getBtnThemeColor () {
                return {
                    color:           '#FFFFFF',
                    backgroundColor: this.$store.state.primaryColor,
                    borderColor:     this.$store.state.primaryColor
                }
            }
        },
        watch: {
            pageBackgroundColor (newval) {
                this.$store.commit('updateColor', {
                    key:  "pageBackgroundColor",
                    value: newval.hex8
                })
            },
            primaryColor (newval) {
                this.$store.commit('updateColor', {
                    key:  "primaryColor",
                    value: newval.hex8
                })
            },
            textPrimaryColor (newval) {
                this.$store.commit('updateColor', {
                    key:  "textPrimaryColor",
                    value: newval.hex8
                })
            },
            textSecondColor (newval) {
                this.$store.commit('updateColor', {
                    key:  "textSecondColor",
                    value: newval.hex8
                })
            }
        },
        data () {
            return {
                user: '',
                todo: [],
                // -------------------
                pageBackgroundColor: this.$store.state.pageBackgroundColor,
                primaryColor:        this.$store.state.primaryColor,
                textPrimaryColor:    this.$store.state.textPrimaryColor,
                textSecondColor:     this.$store.state.textSecondColor,
            }
        }
    }
</script>

由于 vue-color 控件更新回执值是一个对象,因此我是用watch的方式,然后将值通过commit提交给updateColor方法,实现更新。现在来看看效果吧:

图7

Perfect!

五、总结及源代码

使用vuex的store实现了主题颜色切换,正是基于vuex的状态保持特性,使整个app内都可以响应其变化产生的效果。除了使用它保存颜色这些全局属性,按照项目逻辑可以将更多字段保存在vuex里面。vuex是让数据在整个app内贯通及响应,它不会负责持久化保存数据,它在每次运行页面时创建。持久化数据需要自行保存并在vuex创建时将值又赋值给vuex。vuex的用法还有很多,还可以分模块进行状态管理,本文定位vuex入门,更多vuex知识请点击官网文档进行查阅。本文涉及的项目代码你可已通过此链接下载运行:百度网盘,提取码:b2u4。

避坑指南:uniapp动态主题色切换中vuex与mixin的那些坑 本文深入探讨了在UniApp项目中实现动态主题色切换时,如何正确使用Vuex进行状态管理以及规避Mixin的常见陷阱。文章分析了Vuex状态结构设计、性能优化、多端持久化等关键问题,并提供了避免Mixin滥用导致的数据隔离与命名冲突的解决方案,旨在帮助开发者构建健壮、可维护的动态主题系统。 阅读详情

相关推荐

用Codex自动化挖掘电梯行业外贸客户:从关键词到22维深度分析

在B2B外贸客户开发中,精准定位垂直行业潜在客户是核心挑战。传统手动搜索效率低下,而数据驱动的工作流正成为解决方案。其原理在于将模糊的业务需求转化为机器可识别的结构化查询,通过组合行业核心关键词(如“Elevator Manufacturer”、“Elevator Maintenance”)与商业角色描述,系统性地从海量数据中筛选目标。这种自动化抓取技术的价值在于,它不仅生成客户名单,更通过多维数据分析(如公司规模、业务标签、数字足迹)构建初步的客户画像,为后续的优先级排序和个性化触达提供情报基础。在工业制

weixin_34054866的博客 455

uniapp动态主题实践:基于SCSS变量与Vuex的主题切换方案

本文详细介绍了在UniApp中实现动态主题切换的专业方案。通过结合SCSS变量与Vuex状态管理,构建了一套可维护、易扩展的主题系统。SCSS负责样式的定义与计算,Vuex则集中管理主题状态与切换逻辑,实现了应用级别的样式变量动态更新,有效提升了用户体验与开发效率。

weixin_29016315的博客 267

AI Agent在智能投研中的实战:多智能体信息整合与策略生成

本文将带你从0到1完整搭建一套基于LangChain和AutoGen的多智能体AI投研系统首先,我们会一起梳理智能投研的核心痛点、金融数据的独特性,以及为什么传统AI Agent,尤其是多智能体协同架构,是破局的唯一最优解;RAG检索增强生成(但这次是金融领域定制化的,包括向量检索+时序数据检索+知识图谱检索的“三元检索增强”)、AutoGen多智能体协同框架。

软件工程实践的博客 381

vue全局配置elementUI主题,改变全局button底色等

vue全局配置elementUI主题,改变全局button底色等

晚风的博客 2532

PIC单片机应用开发实践教程(二): 新建工程

File---New ProjectMicrochip Embedded --- Standalone Project 选择所用MCU对应型号 点击 Finish 后,工程就建好了 至止,我们的一个新工程就建完成了!

qq_57798018的博客 2888

2021年J题:基于STM32F103的周期信号波形识别与参数测量系统设计(立创EDA+SZPT_ZXL)

本文详细复盘了2021年全国大学生电子设计竞赛J题获奖项目,手把手教你如何基于STM32F103微控制器设计并实现周期信号波形识别与参数测量系统。文章深入剖析了硬件电路设计(包括程控放大、工作点抬升与滞回比较器)与核心软件算法(如动态采样、FFT频谱分析与波形识别逻辑),并分享了DMA传输、FFT库使用等实战要点与避坑指南,为嵌入式信号处理与电赛备赛提供了宝贵经验。

weixin_32673065的博客 230

vue修改整个网页背景色

项目使用的vue+bootstarp响应式网站,修改页面背景色,好用的。注意事项,用完记得移除。

QXHBK的博客 731

ubuntu系统禁止/开启内核自动更新

内核自动更新会导致驱动和内核版本不对应,导致驱动无法使用,所以需要禁止自动更新内核。本文介绍ubuntu系统禁止/开启内核更新的方法。

m0_50105717的博客 5289

vue中实现 ‘换肤 / 切换样式主题’ 功能的三种方式详解

换肤为DeepPink</button><button @click="changeTheme('#1E90FF')">换肤为#1E90FF</button><button @click="changeTheme('#00FF7F')">换肤为#00FF7F

Moon IsLand的博客 3889

智驾芯片新天团!NVIDIA Thor vs 高通8797 vs 蔚来神玑NX9031,2025-2026谁能称王?

应用场景推荐芯片理由高阶NOA + L4 Robotaxi千TOPS以上,满足BEV+TransformerL2+/L3级别NOAThor-U / 高通8797算力适中,功耗控制佳,生态成熟经济型城市NOAThor-Z / S性价比均衡,适合前装普及自研平台一体化NX9031华为之外最强自研整合方案📌 TOPS不再是天花板,GPU、带宽、功耗、上市时间和车企绑定都是决胜关键📌 Thor系列仍然统治高端,但国产神经元开始觉醒📌 智驾芯片的选择,从“强”走向“适合场景”

weixin_43199439的博客 2643

11.嵌入式控制器EC实战 KBC矩阵键盘Keyboard开发流程

文章目录笔记本矩阵键盘概述矩阵键盘的扫描方式行列扫描方式逐行逐列扫描方式EC中矩阵键盘是如何扫描并得到码值的(代码分析) 笔记本矩阵键盘概述 在EC中支持两种形式的键盘,一种是PS/2接口的键盘,这种键盘几乎已经被USB接口的键盘所取代,所以PS/2接口的键盘不在我们的讨论范围。 另一种键盘则是矩阵键盘,也是笔记本电脑的内置键盘,该键盘类似于学习单片机时使用的4*4的那种键盘,笔记本使用的矩阵键盘有三种规格,分别是16*8、17*8和18*8。16、17和18代表着该款键盘的列数,8代表着键盘的行数,我们这

qq_30135687的博客 3809

vue中切换主题颜色

vue中切换主题颜色

qq_39029949的博客 2551

FOC 转子初始位置检测(图文详解)

什么是转子的初始位置? 其实转子的初始位置是不确定的,但是在电机启动的时候,我们需要得到电角度,这样才可以进行矢量控制;所以,这里将转子与A轴重合作为初始位置,此时电角度也恰好为零,具体如下图所示; ) 至于原理下面会详细分析,这样在转子到初始位置后,也可以得到准确的电角度,就可以实现磁场和转子的同步转动。 如何让转子运行到初始位置? 其实这是一个很简单的问题,在这里我将它放大了,简单地分析了一...

一名热爱技术的工程师的博客。分享技术干货,记录美好生活。永远相信美好的事情即将发生。 2万+

vue主题颜色切换

/ 蓝色 /***********************************************************************************************************************/ .Blue {// 左侧整体背景颜色} //左侧导航背景//左侧导航背景.el-menu {} //左侧导航背景鼠标焦点颜色 --el-color-primary-light-9 : #3656b5;} // logo颜色。

王兆镇的博客 2960

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Element Plus全局主题修改最佳实践

- 目标:实现 Element Plus 组件库的全局主题切换(如明暗模式、主色调自定义等),并支持用户个性化设置,且能持久化保存用户选择。 - 适用场景:后台管理系统、企业级应用、需要多主题切换的前端项目。

m0_73579391的博客 2801

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

vue+elementUI的主题颜色多文件切换

1.安装vue-cli npm install -g vue-cli vue init webpack vue_demo cd vue_demo npm install npm run dev 2.安装element-ui及sass npm i element-ui -S npm install --save-dev sass-loader npm install --save-dev node-sass 在build文件夹下的webpack.base.conf.js

sumimg的博客 1367

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

为什么在 Vue3 中,动态换肤不能直接用 Vuex 管理颜色?

light: {},dark: {2. 主题切换逻辑// 遍历主题变量,更新到根元素});// 可选:保存到 localStorage 或 Vuex3. 集成 ElementUI 主题// main.js// 初始化时加载默认主题4. 在组件中使用 CSS 变量<template>-- 直接使用 CSS 变量,无需访问 Vuex --><el-button type="primary">按钮</el-button></div>.header {</style>

2501_92234528的博客 830

Web前端主题色更换实现方式全解析(二)

基于前端框架的主题色切换

球球不吃虾WHR2349博客 3129

vue-element-admin主题定制指南:实现多主题切换功能的终极教程

vue-element-admin作为基于Vue.js和Element UI的优秀后台管理系统模板,其强大的主题定制功能让开发者能够轻松实现多主题切换效果。本文将详细介绍如何利用vue-element-admin的主题系统,打造个性化的后台管理界面。✨ ## 什么是vue-element-admin主题定制功能? vue-element-admin提供了完整的主题定制解决方案,允许开发者在不修

gitblog_00563的博客 979

vue项目主题切换(换肤)从0-1的实现

vue项目、换肤、切换主题从0-1到的实现

weixin_43695002的博客 2591

Vue-Element-Plus-Admin 主题切换技术揭秘:深色模式与自定义主题实现指南

Vue-Element-Plus-Admin 是一款基于 Vue3、TypeScript、Element-Plus 和 Vite 构建的后台管理系统,其强大的主题切换功能让用户能够轻松在深色模式与浅色模式之间切换,同时支持完全自定义的主题配置。本文将深入揭秘该系统的主题切换技术实现原理,帮助开发者理解如何在自己的项目中实现类似功能。 ## 主题切换的核心实现机制 Vue-Element-Plu

gitblog_00971的博客 861

动态修改主题色(uni-app、H5)

非 web 端(包含小程序和 App),Android 平台运行在 v8 引擎中,iOS 平台运行在 iOS 自带的 jscore 引擎中,都没有运行在浏览器或 webview 里,因此不支持 window、document、navigator 等浏览器专用对象。这里关键是使用el.style.setProperty()方法可以修改css变量的值,示例没有做持久化储存,刷新会丢失,可自行添加。具体使用要看具体需求,如果只是浅色主题和深色主题等更换,只需要在state把主题的配置写好,用开关控制即可。

Zzzz__111的博客 2997

ant-design-vue-pro中的主题切换:实现深色模式的完整方案

你是否曾在深夜使用管理系统时被刺眼的白色界面困扰?是否希望应用能像手机系统一样随环境切换明暗主题?本文将带你了解如何在ant-design-vue-pro中实现深色模式切换,通过简单配置即可让系统拥有日夜两种界面风格,提升用户体验。 ## 主题切换的核心配置文件 ant-design-vue-pro的主题配置主要集中在两个关键文件中:全局默认设置和主题切换逻辑实现。 **默认主题设置**定义...

gitblog_00959的博客 922

Vue2暗黑模式实战:从零实现深色/浅色主题切换(附完整代码)

本文详细介绍了在Vue2项目中实现暗黑模式的完整方案,包括CSS变量定义、Vuex状态管理、Element UI适配等核心步骤。通过实战代码演示如何实现深色/浅色主题切换功能,并提供了护眼效果、省电优势等实用价值分析,帮助开发者快速为Vue2应用添加专业的主题切换能力。

weixin_29003437的博客 228

Vue Antd Admin 主题定制完全指南

Vue Antd Admin 作为一款优秀的中后台前端解决方案,提供了强大的主题定制能力。本文将全面介绍如何在该项目中定制主题颜色、主题模式、导航布局等视觉元素,帮助你打造独具特色的管理系统界面。 ## 主题颜色定制 ### 1. 主题色配置 系统内置了7种预设主题色供选择: - 火山红 (#fa541c) - 日暮黄 (#fadb14) - 极光绿 (#3eaf7c) - 明青 (#13...

gitblog_00586的博客 629

Vue3实战:用Provide/Inject打造全局主题切换功能(附完整代码)

本文详细介绍了在Vue3项目中,如何利用Provide/Inject组合式API构建一个类型安全、响应式的全局主题切换系统。通过对比其他状态管理方案,阐述了其轻量级、类型安全、作用域可控的优势,并提供了完整的主题提供者组件、组合式函数及UI组件实现代码,帮助开发者优雅地解决跨多层组件共享状态的问题。

q3r4s5t的博客 550
上一篇: 【Vue】使用Vue实现div收缩效果
下一篇: 【JavaScript】Promise教程、Promise的使用。
Microanswer
博客等级 码龄10年 38粉丝 40原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值