Vue常用插件:vuex

简介

Vue全家桶中的状态管理工具

Typescript中使用vuex参考:基于Typescript的Vue项目中使用vuex

安装

插件安装:npm i vuex --save

store定义

简单使用

  • src目录下新建目录store
  • src/store目录下新建index.js文件
import Vue from 'vue' import Vuex from 'vuex' import createLogger from 'vuex/dist/logger' // state const state = { indexCount: 0 } // getters const getters = { indexCount: state => state.indexCount } // mutations const mutations = { setIndexCount(state, n) { state.indexCount = n }, addIndexCount(state) { state.indexCount++ } } // actions const actions = {} Vue.use(Vuex) const debug = process.env.NODE_ENV !== 'production' export default new Vuex.Store({ actions, getters, state, mutations, strict: debug, plugins: debug ? [createLogger()] : [] })

抽离文件

项目较大时,推荐将stategettersmutationsactions放在单独的文件中

  • src/store/index.js
import Vue from 'vue' import Vuex from 'vuex' import * as actions from './actions' import * as getters from './getters' import state from './state' import mutations from './mutations' import createLogger from 'vuex/dist/logger' Vue.use(Vuex) const debug = process.env.NODE_ENV !== 'production' export default new Vuex.Store({ actions, getters, state, mutations, strict: debug, plugins: debug ? [createLogger()] : [] })
  • src/store/目录下新建state.jsgetters.jsmutations.jsactions.js文件,分别用来存放stategettersmutationsactions

分模块处理

项目较大时也可以分模块处理
比如src/store/目录下这种结构(appuser两个模块)

  • src/store/index.js文件
import Vue from 'vue' import Vuex from 'vuex' import app from './modules/app' import user from './modules/user' import getters from './getters' Vue.use(Vuex) const store = new Vuex.Store({ modules: { app, user }, getters }) export default store
  • src/store/目录下新建getters.js文件
const getters = { sidebar: state => state.app.sidebar, visitedViews: state => state.app.visitedViews, token: state => state.user.token, avatar: state => state.user.avatar, name: state => state.user.name, } export default getters
  • src/store/目录下新建modules/目录
  • src/store/modules/目录下新建app.js文件
import Cookies from 'js-cookie' const app = { state: { sidebar: { opened: !+Cookies.get('sidebarStatus') }, visitedViews: [] }, mutations: { TOGGLE_SIDEBAR: state => { if (state.sidebar.opened) { Cookies.set('sidebarStatus', 1) } else { Cookies.set('sidebarStatus', 0) } state.sidebar.opened = !state.sidebar.opened }, ADD_VISITED_VIEWS: (state, view) => { if (state.visitedViews.some(v => v.path === view.path)) return state.visitedViews.push({ name: view.name, path: view.path }) }, DEL_VISITED_VIEWS: (state, view) => { let index for (const [i, v] of state.visitedViews.entries()) { if (v.path === view.path) { index = i break } } state.visitedViews.splice(index, 1) } }, actions: { ToggleSideBar({ commit }) { commit('TOGGLE_SIDEBAR') }, addVisitedViews({ commit }, view) { commit('ADD_VISITED_VIEWS', view) }, delVisitedViews({ commit, state }, view) { return new Promise((resolve) => { commit('DEL_VISITED_VIEWS', view) resolve([...state.visitedViews]) }) } } } export default app
  • src/store/modules/目录下新建user.js文件,内容参考app.js

vue文件中使用

  • 修改src/main.js文件
// ... import store from './store' // ... /* eslint-disable no-new */ new Vue({ el: '#app', store, components: { App }, template: '<App/>' })
  • 读取state数据
console.log(this.$store.state.indexCount)
  • 使用辅助函数读取state数据
import { mapState } from 'vuex' export default { // ... computed: mapState({ // 箭头函数可使代码更简练 count: state => state.count, // 传字符串参数 'count' 等同于 `state => state.count` countAlias: 'count', // 为了能够使用 `this` 获取局部状态,必须使用常规函数 countPlusLocalState (state) { return state.count + this.localCount } }), // 也可以传一个数组 // computed: mapState([ // // 映射 this.count 为 store.state.count // 'count' // ]) }
  • 读取getters数据
this.$store.getters.indexCount
  • 使用辅助函数读取getters数据
import { mapGetters } from 'vuex' export default { // ... computed: { // 使用对象展开运算符将 getter 混入 computed 对象中 // 方法类似mapState,同样也可以传入一个对象 ...mapGetters([ 'doneTodosCount', 'anotherGetter', // ... ]) } }
  • 使用mutations修改数据
this.$store.commit('setIndexCount', 6)
  • 使用辅助函数commit
import {mapMutations} from 'vuex' export default { // ... methods: { ...mapMutations({ setCount: 'setIndexCount' }), // ... // this.setCount(6) }
  • 使用actions
this.$store.dispatch('GetUserInfo')
  • 使用辅助函数dispatch
import { mapActions } from 'vuex' export default { // ... methods: { ...mapActions([ 'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')` // `mapActions` 也支持载荷: 'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)` ]), // ...mapActions({ // add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')` // }) } }

js文件中使用

import store from '../store/index' console.log(store.state.indexCount) store.commit('setIndexCount', 6)

其他

如果mutations中有很多类似这种代码

const state = { b: '', info: {}, ExecNum: 0, // ... } const mutations = { setB(state, b) { state.b = b }, setInfo(state, info) { state.info = info }, setExecNum(state, ExecNum) { state.ExecNum = ExecNum }, // ... }

我们可以将其改造下

const state = { b: '', info: {}, ExecNum: 0, // ... } const mutations = { ...generateMutations(['b', 'info', 'ExecNum']), // ... } /** * @param arr:数组,数组中每项是 state 的key值 * @return 一个对象 * 比如输入数组某项值为info, * 对应的输出 setInfo: (state, value) => { state.info = value } */ function generateMutations(arr) { if (!Array.isArray(arr)) return {} const res = {} arr.forEach(item => { // 首字母大写 const stateName = item.charAt(0).toUpperCase() + item.slice(1) res[`set${stateName}`] = (state, value) => { state[item] = value } }) return res }

参考链接


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

 分享给好友: