• 简述Vue中使用Vuex


    1、为什么要用vuex

          在vue组件通信的过程中,我们通信的目的往往就是在组件之间传递数据或组件的状态(这里将数据和状态统称为状态),进而更改状态。但可以看到如果我们通过最基本的方式来
    进行通信,一旦需要管理的状态多了,代码就会变得十分混乱。对所有状态的管理便会显得力不从心,尤其是多人合作的时候。此时vuex出现了,他就是帮助我们把公用的状态全抽出来放
    在vuex的容器中,然后根据一定的规则来进行管理。

    2、概念

    • 概念:vuex是一个状态管理工具,每一个Vuex应用的核心就是store(仓库);“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state),它的实例是唯一的-----单例模式;  一般把需要共享的数据放到store中;
    • 功能:存数据、取数据、改数据;
    • 出现场景:
      • 涉及到非父子关系的组件,例如兄弟关系、祖孙关系,甚至更远的关系组件之间的联系;
      • 在大型单页应用中,考虑如何更好地在组件外部管理状态;
    • 注意:vuex的数据处理流程是一个"单向"的数据流 ;
    • vuex的核心:
      • state:存放数据(状态);    取数据  this.$store.state.变量名
      • mutations:存放如何更改状态,同步方法放到mutations(同步)里面;    调用方法 this.$store.commit("方法名","参数")
      • getters:相当于计算属性,从state中派生出状态,比如将state中的某个状态进行过滤然后获取新的状态;      this.$store.getters.方法名(sum)
      • actions:mutations的加强版,异步方法放在了actions(动作)里面;      调用方法this.$store.dispatch("方法名"),异步方法则会调用mutations里面的同步方法
      • modules:就是当用这个容器来装这些状态还是显得混乱的时候,我们就可以把容器分成几块,把状态和管理规则分类来装。这和我们创建js模块是一个目的,让代码结构更清晰。

    3、基本使用

    • vuex的安装
      cnpm i vuex --save
    • 安装成功后,
      • 新手入门    注意:vuex中是不允许直接修改store的状态值,我们必须通过mutations进行修改操作
        • 新建store文件夹,内容如下

                                   

        • 在app.js里面进行引入
          import store from './store'
          new Vue({
              router,
              i18n,
              store,
              el: '#app',
              render: h => h(App)
          })
        • store文件夹中index.js的内容为
          import Vue from 'vue'
          import Vuex from 'vuex'
          
          import state from './state'
          import actions from './actions'
          import mutations from './mutations'
          
          Vue.use(Vuex)
          
          export default new Vuex.Store({
              state,
              actions,
              mutations
          })
        • 在state.js中定义状态
          export default {
              count: 1,
          }
        • 在mutations.js里面定义同步方法
          export default {
              // 改变状态的执行者   用于同步更改状态
              stateMutationsAdd(state, payLoad) {
                  // 第一个参数是state   第二个参数是调用mutations时传入的参数
                  state.count += payLoad;
              },
              stateMutationsReduce(state, payLoad) {
                  state.count -= payLoad;
              }
          }
        • 在actions.js里面定义异步操作
          export default {
              // actions并不直接更改状态   而是发起mutations来更改状态
              stateAsyncReduce(context) {
                  // context 是一个与 store 实例具有相同方法和属性的 context 对象
                  // 这个异步操作  我们可以发送http请求、定时器、
                  setTimeout(() => {
                      context.commit("stateMutationsReduce", 5)//不能用this.$store,为undefined
                  }, 1000)
              }
          }
        • 在vue组件中使用(将state与getters结合进组件需要使用计算属性,将mutations与actions结合进组件需要在methods里面进行调用)
          <template>
            <div class="home">
              <div class="block">
                <h1>vuex的基本使用</h1>
                <el-button size="mini" type="primary" @click="reduceNumber">-</el-button>
                &nbsp;&nbsp;{{count}}
                <el-button size="mini" type="primary" @click="addNumber">+</el-button>
                <h1>vuex练习结束</h1>
              </div>
            </div>
          </template>
          <script>
          export default {
            name: "home",
            data() {
              return {};
            },
            computed: {
              count() {
                return this.$store.state.count;
              }
            },
            methods: {
              /**
               * [addNumber  对count数据进行增加操作  采用同步方式]
               * @return {[type]} [description]
               */
              addNumber() {
                // 第一个参数是同步方法的名称   第二个参数是传递给方法的数据
                this.$store.commit("stateMutationsAdd", 10);
              },
              /**
               * [reduceNumber  对count数据进行减少操作   采用异步方式]
               * @return {[type]} [description]
               */
              reduceNumber() {
                // dispatch返回的是actions执行的结果,是一个promise对象,如果异步操作之后还需要其他操作,可以使用.then/.catch等
                this.$store.dispatch("stateAsyncReduce");
              }
            },
            mounted() {}
          };
          </script>
          View Code
        • 效果图

                                 

            点击 + 进行同步增加     

            点击-进行异步减少,每隔1s减少5

      • 新手入门之后,我们可以尝试将mutations里面的一些方法名称提取出来,从而提高代码维护性;
        • state.js
          export default {
              count: 1,
          }
        • mutation-types.js
          export const STATE_MUTATIONS_ADD = 'stateMutationsAdd'
          export const STATE_MUTATIONS_REDUCE = 'stateMutationsReduce'
        • mutations.js
          import { STATE_MUTATIONS_ADD, STATE_MUTATIONS_REDUCE } from './mutation-types'
          export default {
              // 改变状态的执行者   用于同步更改状态
              [STATE_MUTATIONS_ADD](state, payLoad) {
                  // 第一个参数是state   第二个参数是调用mutations时传入的参数
                  state.count += payLoad;
              },
              [STATE_MUTATIONS_REDUCE](state, payLoad) {
                  state.count -= payLoad;
              }
          }
          View Code
        • actions.js
          import { STATE_MUTATIONS_ADD, STATE_MUTATIONS_REDUCE } from './mutation-types'
          export default {
              // actions并不直接更改状态   而是发起mutations来更改状态
              stateAsyncReduce(context) {
                  // context 是一个与 store 实例具有相同方法和属性的 context 对象
                  // 这个异步操作  我们可以发送http请求、定时器、
                  setTimeout(() => {
                      context.commit(STATE_MUTATIONS_REDUCE, 5)//不能用this.$store,为undefined
                  }, 1000)
              }
          }
          View Code
        • vue组件中的使用
          <template>
            <div class="home">
              <div class="block">
                <h1>vuex的基本使用</h1>
                <el-button size="mini" type="primary" @click="reduceNumber">-</el-button>
                &nbsp;&nbsp;{{count}}
                <el-button size="mini" type="primary" @click="addNumber">+</el-button>
                <h1>vuex练习结束</h1>
              </div>
            </div>
          </template>
          <script>
          import {
            STATE_MUTATIONS_ADD,
            STATE_MUTATIONS_REDUCE
          } from "../store/mutation-types";
          export default {
            name: "home",
            data() {
              return {};
            },
            computed: {
              count() {
                return this.$store.state.count;
              }
            },
            methods: {
              /**
               * [addNumber  对count数据进行增加操作  采用同步方式]
               * @return {[type]} [description]
               */
              addNumber() {
                // 第一个参数是同步方法的名称   第二个参数是传递给方法的数据
                this.$store.commit(STATE_MUTATIONS_ADD, 10);
              },
              /**
               * [reduceNumber  对count数据进行减少操作   采用异步方式]
               * @return {[type]} [description]
               */
              reduceNumber() {
                // dispatch返回的是actions执行的结果,是一个promise对象,如果异步操作之后还需要其他操作,可以使用.then/.catch等
                this.$store.dispatch("stateAsyncReduce");
              }
            },
            mounted() {}
          };
          </script>
          View Code
      • 为了方便起见,利用vuex提供的mapState、mapGetters、mapMutations以及mapActions四个方法将这些功能结合进组件
        • 其他文件跟上述保持一致
        • vue组件中的使用
          <template>
            <div class="home">
              <div class="block">
                <h1>vuex的基本使用</h1>
                <el-button size="mini" type="primary" @click="stateAsyncReduce">-</el-button>
                &nbsp;&nbsp;{{count}}
                <p>使用getters{{name}}</p>
                <el-button size="mini" type="primary" @click="stateMutationsAdd(10)">+</el-button>
                <h1>vuex练习结束</h1>
              </div>
            </div>
          </template>
          <script>
          import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
          export default {
            name: "home",
            data() {
              return {};
            },
            computed: {
              ...mapState(["count"]),
            },
            methods: {
              ...mapActions(["stateAsyncReduce"]),
              ...mapMutations(["stateMutationsAdd"])
            },
            mounted() {}
          };
          </script>
          View Code
      • 当你采用了上述方式进行整合之后,依旧存在过多的状态,导致代码混乱的现象,我们可以将store分割成模块(module),每个模块都拥有自己的state、getters、mutations以及actions,甚至是嵌套子模块,从上至下按照同样的方式进行分割。
        • 首先,我们看一下目录结构

                                  

        •  store/index.js
          import Vue from 'vue'
          import Vuex from 'vuex'
          import * as actions from './actions'
          import modules from './modules'
          Vue.use(Vuex)
          export default new Vuex.Store ({
              actions,
              modules,
              strict: false
          })
        • store/mutation-types.js
          export const STATE_MUTATIONS_ADD = 'stateMutationsAdd'
          export const STATE_MUTATIONS_REDUCE = 'stateMutationsReduce'
        • store/actions.js(大型项目中我们可以将所有的异步操作提取出来)
          import * as types from './mutation-types'
          const makeAction = (type) => {
            return ({ commit }, ...args) => commit(type, ...args)
          }
          export function stateAsyncReduce(context) {
            // context 是一个与 store 实例具有相同方法和属性的 context 对象
            // 这个异步操作  我们可以发送http请求、定时器、
            setTimeout(() => {
              context.commit(types.STATE_MUTATIONS_REDUCE, 5)//不能用this.$store,为undefined
            }, 1000)
          }
        • module/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
        • module/home.js(home可以自定义,以后项目中随机建立的模块名称)
          import { STATE_MUTATIONS_ADD, STATE_MUTATIONS_REDUCE } from '../mutation-types'
          const state = {
              count: 1
          }
          
          const mutations = {
              [STATE_MUTATIONS_ADD](state, payLoad) {
                  // 第一个参数是state   第二个参数是调用mutations时传入的参数
                  state.count += payLoad;
              },
              [STATE_MUTATIONS_REDUCE](state, payLoad) {
                  state.count -= payLoad;
              }
          }
          
          export default {
              state,
              mutations
          }
          View Code
        • vue组件中的使用
          <template>
            <div class="home">
              <div class="block">
                <h1>vuex的基本使用</h1>
                <el-button size="mini" type="primary" @click="stateAsyncReduce">-</el-button>
                <span>{{count}}</span>
                <el-button size="mini" type="primary" @click="stateMutationsAdd(10)">+</el-button>
                <h1>vuex练习结束</h1>
              </div>
            </div>
          </template>
          <script>
          import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
          export default {
            name: "home",
            data() {
              return {};
            },
            computed: {
              ...mapState({
                count: state => state.home.count
              })
            },
            methods: {
              ...mapActions(["stateAsyncReduce"]),
              ...mapMutations(["stateMutationsAdd"])
            },
            mounted() {}
          };
          </script>
          View Code
        • 特别强调的是:
          ...mapState({
             count: state => state.home.count(home为模块的名称)
          })

    4、遇到的问题

       暂无

  • 相关阅读:
    POI中文API文档
    接口
    JDK中的URLConnection参数详解
    RPC远程过程调用概念及实现
    tkinter 打包成exe可执行文件
    PHP 的命令行模式
    php CLI SAPI 内置Web Server
    ppython的移位操作
    HAProxy基础
    HAProxy用法详解
  • 原文地址:https://www.cnblogs.com/wxh0929/p/11984417.html
Copyright © 2020-2023  润新知