在 vue.js 项目中使用 vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。 它采用集中式存储管理应用的所有组件的状态, 并以相应的规则保证状态以一种可预测的方式发生变化。 这里就简单的介绍 vuex 的使用方法

文档

vuex 官方文档

关于 vuex 的严格模式

在 vuex 有个参数是 strict 这个是可以配置 vuex 开启严格模式, 这里极力推荐开启严格模式, 当然是在开发模式下, 线上模式可以进行关闭, 因为我们不希望内部逻辑暴露在外面。

至于为什么极力推荐开启 vuex 的严格模式, 有以下这些原因:

  • 官方也是这么推荐的, vuex 中的数据被称作 state, 这些数据通过 getters 将其暴露给组件使用, 那么要想改变其值只能在 vuex 内部实现(即 modules 和 actiions, 具体可以阅读官方文档)
  • vuex 被设计出来就是一个第三方的状态管理仓库, 当然这些状态也只能由内部的逻辑实现, 外部也可以对 state 的值进行改变, 但是不推荐
  • 我们常说的 cookie 也好 session 也好, 它们有个致命的弱点, 就是比较容易被窃取, 那么 vuex 就规避了这些缺点, 因为所有的数据都在 vuex 的 store 仓库, 只能由 vuex 内部的状态来管理, 就不容易被窃取, 如果由外部的逻辑来改变 state 值, 那么 vuex 的安全性岌岌可危

更多详情请阅读 vuex 严格模式

关于 vuex

  • state => 单一状态树,数据存储库,即驱动应用的数据源
  • getter => 派生出 state 的值
  • mutation => 更改状态的唯一途径,直接修改状态
  • action => 提交 mutation,不是直接修改状态,相应在 view 上的用户输入导致状态的变化
  • module => 整合一个模块的 stategettermutationaction
  • view => 以声明方式将 state 映射到视图

install

使用命令安装 vuex 依赖

npm i -D vuex
# or
yarn add vuex

目录结构

我们单独创建一个 store 目录, 目录结构大致是

|-- src
  |-- store
    |-- modules
      |-- index.js
      |-- ... ...
    |-- getters.js      # 根级别的 mutation =>
    |-- index.js        # 我们组装模块并导出 store 的地方
    |-- mutation-types.js        # 根级别的 type => 状态
  |-- main.js

导入 vuex

src/mian.js

import Vue from 'vue'
import store from '@/store'
Vue.config.productionTip = false
new Vue({
    store, 
    render: h => h(App), 
}).$mount('#app')

strore/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import modules from './modules'
import getters from './getters'
Vue.use(Vuex)
const debug = true // 推荐开启严格模式
export default new Vuex.Store({
    modules, 
    getters, 
    strict: debug
})

strore/getters.js

const getters = {
    [stateName]: state => state. [modulesName]. [stateName]
}
export default getters

store/modules/index.js

const files = require.context('.', false, /\.js$/)
const modules = {}
files.keys().forEach(key => {
    if (key === './index.js') return
    modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
})
export default modules

store/mutation-types.js

// 这边必须使用全大写, 没有为什么
export const TYPES_NAME = 'TYPES_NAME'

vuex 食用例子

做完以上的工作之后我们就可以进行使用 vuex 了, 下方举一个最简单的两个数的 加减乘除 的例子

在线访问 Edit on CodeSandbox

store/mutation-types.js

export const ADDITION = 'ADDITION' // + 加法
export const SUBSTRUCTION = 'SUBSTRUCTION' // - 减法
export const MULTIPLICATION = 'MULTIPLICATION' // * 乘法
export const DIVISION = 'DIVISION' // / 除法

store/modules/operation.js

import {
    ADDITION, 
    SUBSTRUCTION, 
    MULTIPLICATION, 
    DIVISION
} from '@/store/mutation-types'
const operation = {
    state: {
        result: 0
    }, 
    mutations: {
        [ADDITION]: (state, payload) => {
            state.result = Number(payload.a) + Number(payload.b)
        }, 
        [SUBSTRUCTION]: (state, payload) => {
            state.result = Number(payload.a) - Number(payload.b)
        }, 
        [MULTIPLICATION]: (state, payload) => {
            state.result = Number(payload.a) * Number(payload.b)
        }, 
        [DIVISION]: (state, payload) => {
            state.result = Number(payload.a) / Number(payload.b)
        }
    }, 
    actions: {
        addition({
            commit
        }, payload) {
            commit(ADDITION, payload)
        }, 
        substrction({
            commit
        }, payload) {
            commit(SUBSTRUCTION, payload)
        }, 
        multiplication({
            commit
        }, payload) {
            commit(MULTIPLICATION, payload)
        }, 
        division({
            commit
        }, payload) {
            commit(DIVISION, payload)
        }
    }
}
export default operation

store/getters.js

const getters = {
    result: state => state.operation.result
}
export default getters

views/Operation.vue

<template>
  <div>
    <div>
      <input type="number" v-model="payload.a" placeholder="参数 A" style="margin:0 5px;height:18px;width:50px;" />
      {{ operation }}
      <input type="number" v-model="payload.b" placeholder="参数 B" style="margin:0 5px;height:18px;width:50px;" />
      = {{ result }}
    </div>
    <div style="margin-top:10px">
      <button @click="addition" style="margin:0 5px;">+</button>
      <button @click="substrction" style="margin:0 5px;">-</button>
      <button @click="multiplication" style="margin:0 5px;">*</button>
      <button @click="division" style="margin:0 5px;">/</button>
    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  data () {
    return {
      operation: '+', 
      payload: {
        a: 0, 
        b: 0
      }
    }
  }, 
  computed: {
    ...mapGetters(['result'])
  }, 
  methods: {
    addition () {
      this.operation = '+'
      this.$store.dispatch('addition', this.payload)
    }, 
    substrction () {
      this.operation = '-'
      this.$store.dispatch('substrction', this.payload)
    }, 
    multiplication () {
      this.operation = '*'
      this.$store.dispatch('multiplication', this.payload)
    }, 
    division () {
      this.operation = '/'
      this.$store.dispatch('division', this.payload)
    }
  }
}
</script>
亲!!! 听说给作者打赏一杯咖啡钱,会给自己带来好运哦!