vue项目配置4-Vuex状态管理-Vuex使用详解

版权声明:作者:shenroom 来源:CSDN 版权声明:本文为博主原创文章,转载请附上博文链接! https://blog.csdn.net/qq_41772754/article/details/88074103
一下是根据自己 百度以及官网的学习,整理出的 vuex 基本用法
(下面是废话,可以直接跳过)
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
  问题1: 多个视图依赖于同一状态。
  问题2: 来自不同视图的行为需要变更同一状态
对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。

因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?
在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
另外,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将会变得更结构化且易维护。

什么情况下我应该使用 Vuex?
虽然 Vuex 可以帮助我们管理共享状态,但也附带了更多的概念和框架。这需要对短期和长期效益进行权衡。
如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。
一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。

每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。
Vuex 和单纯的全局对象有以下两点不同:
1.Vuex 的状态存储是响应式的,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
2.你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。

1.NPM安装

    npm install vuex --save

2.配置store中的文件
在 src 目录下创建 store 文件夹,并在里面创建一些文件,结构如下

src
 ├── ...
 └── store
       ├── modules  // 模块化
       │      ├── page1.js // 对应的组件页面,一般不同的页面中使用到的数据,分开存放,比如home页,个人中心页,等
       │      └── page2.js //
       └── index.js // 所有组件公用的数据 放在同一个页面,看个人习惯,数据多的话就在modules文件中创建一个public.js存放,数据少的话就直接放在index.js中即可,这样方便管理数据
a) index.js 中的内容:
import Vue from 'vue'
import Vuex from 'vuex'

import page1 from './modules/page1' // 将page1.js文件导入
import page2 from './modules/page2' // 将page1.js文件导入

Vue.use(Vuex);

//------1.属性 state :全局访问的state对象,存放要设置的初始属性及值-------------------------------------------------
const state={                  
  showFooter: true,
  obj:{ b:2 }   
}
/*
  在组件实例中可如下获取 showFooter 和 obj 值:
    this.$store.state.showFooter
    this.$store.state.obj
  注:这不是理想的获取方式(不推荐使用),一般使用getters方法获取,如下:
*/

//------2.属性 getters :实时监听state值的变化(最新状态)---------------------------------------------------------------
const getters = {              
  showFooter(state) {              // 承载变化的 showFooter 的值,名字可随便取,一般跟state中设置的变量名相同。(主要看个人喜好)
    return state.showFooter        // 需跟state中的变量相对应
  },
  obj(){                           // 承载变化的 obj 的值,
    return state.obj
  }
}
/*
  在组件实例中可如下获取 showFooter 和 obj 值:
    this.$store.getters.showFooter
    this.$store.getters.obj
  注:这是理想的获取方式,能实时监听state值的变化(最新状态),推荐使用。
*/

//------3.属性 mutations :里面可以存放改变 state 的初始值的方法 ( 同步操作 )-------------------------------------------
const mutations = {
  showFooter(state,val) {          // 自定义改变state初始值的方法,这里面的参数除了state之外还可以再传额外的参数(变量或对象);
    state.showFooter = val;
  },
  obj(state,val){                  // 同上,这里面的参数除了 state 之外还传了参数 b
    state.obj = val;
  }
}
/*
  在组件中调用下列方法如下:
    this.$store.commit('showFooter',false)
    this.$store.commit('obj',{a:1})
  注:这不是理想的改变值的方式,因为在不同组件里执行同一方法得到的值是一样的,需要使用actions配合,如下
*/

//------4.属性 actions :里面可以存放用来异步触发 mutations 里面的方法的方法 ( 异步操作 )--------------------------------
const actions = {
  showFooter(context,val) {       // 同上注释
    context.commit('showFooter',val);
  },
  obj(context,val){                // 同上注释,num为要变化的形参
    context.commit('obj',val)
  }
}
/*
  在组件中调用下列方法如下:
  this.$store.dispatch('showFooter',false)
  this.$store.dispatch('newObjRun',{a:1})  
  注:理想的操作改变值的方式
*/

//------5.属性 modules :存放模块化的数据,page1.js和page2.js(关于组件中引入 mapGetters、mapActions 和 mapStates 的使用)-------------------------------
const modules = {  // 
  page1,
  page2
}

//创建一个 store 实例
const store = new Vuex.Store({
   state,
   getters,
   mutations,
   actions,
   modules
})

export default store

b).page1.js 中的内容:( page1.js使用的是普通语法,数据结构和 page2.js一样)

export default {
  namespaced:true,                       //用于在全局引用此文件里的方法时标识这一个的文件名
  state:{
    arr:["a"],                           //初始化一个 arr 数组
  },
  getters:{
    getArr:function(state){              //实时监听 state 值的变化(最新状态)
      return state.arr
    }
  },
  mutations:{
    pushArr:function(state,items){       //自定义改变 state 初始值的方法,参数除了state之外还可以再传额外的参数(变量或对象)
      state.arr.push(items)
    }
  },
  actions:{
    pushArrRun:function(context,item){   //自定义触发 mutations 里函数的方法,context与store 实例具有相同方法和属性
      context.commit('pushArr',item)
    }
  }
}

c). page2.js 中的内容:( page2.js使用的是ES6语法。page1.js,page2.两个写法一样,看个人喜好,推荐使用ES6语法)

const state={         
  sum:1                //初始化一个 sum
}
const getters = {      //实时监听state值的变化(最新状态)
  getSum: () => state.sum
}
const mutations = {    //自定义改变state初始值的方法,参数除了state之外还可以再传额外的参数(变量或对象)
  add: (state,m) => state.sum += m 
}
const actions = {      //自定义触发mutations里函数的方法,context与store 实例具有相同方法和属性
  addTo:(context,m) => context.commit('add',m)
}
export default {
  namespaced: true,    //用于在全局引用此文里的方法时标识这一个的文件名
  state,
  getters,
  mutations,
  actions
}

d). 最后一步   在 main.js 中将 配置好的Vuex 挂载(注入)到vue 实例中

//.......
import store from './store'

new Vue({
  el: '#app',
  router,
  store,         //注入,组件中可以使用 this.$store 获取
  components: { App },
})

到此,Vuex 就配置完成了,简单大致梳理一下配置流程:

    1.声明 state 对象,存放要 设置 的数据对象

    2.声明 getters 对象,存放 获取 state中数据的方法

    3.声明 mutations 对象,存放 设置 state中数据的方法

    4.声明 actions 对象,存放 异步操作 mutations中的方法的方法(有点绕口)

    5.声明 modules 对象, 存放 外部模板 文件 (如果没有创建外部 js 文件,次步可去除)

    6.创建 Vuex 实例,注入上面声明的对象,并用export default导出,然后再在main.js中将 Vuex 挂在到Vue实例中 

再简单看一下基本使用的语法:

    1.获取 某个状态的值:  index.js   中的 obj 的值:this.$store.getters.obj

                                        page1.js  中的 arr 的值:this.$store.getters[ "page1/arr" ]

    2.设置 某个状态的值:  index.js   中的 obj 的值:this.$store.dispatch( "obj" , val )

                                        page1.js 中的 arr 的值:this.$store.dispatch( "page1/arr" , val )

使用和设置就是这摸简单,当然还有更高级的模块化用法,下文会介绍

3.在项目组件中使用 Vuex 

1.基本语法使用

<template>
  <div class="test">
    <button @click="push">拖鞋</button>
    <button @click="push">上衣</button>
    <button @click="push">帽子</button>
    <p>所有物品:{{ arrData }}</p>
    <p>总件数:{{ sumData }}</p>
    <p>总信息:{{ objData }}</p>
  </div>
</template>

<script>
export default {
  data () {
    return { }
  },
  computed:{
    objData(){
      // return this.$store.state.obj        
      return this.$store.getters.obj                 // 该方式获取 store/index.js 中的 obj ,比上面方式更理想
    },
    arrData(){
      // return this.$store.state.page1.arr
      return this.$store.getters['page1/getArr']     // 该方式获取 store/module/page1.js 中的 arr ,比上面方式更理想
    },
    sumData(){
      // return this.$store.state.page2.sum
      return this.$store.getters['page2/getSum']     // 该方式获取 store/module/page2.js 中的 sum ,比上面方式更理想
    }
  },
  methods:{  
    getDatas(s){                                     // 获取 store/index.js 中对象 actions 的 obj方法
      this.$store.dispatch('obj', s)
    },
    pushArr(s){                                      // 获取 store/module/page1.js 中对象 actions 的 pushArrRun 方法
      this.$store.dispatch('page1/pushArrRun', s)    
    },
    add(s){                                          // 获取 store/module/page2.js 中对象 actions 的 addTo 方法
      this.$store.dispatch('page2/addTo', s)         
    },
    push:function(e){
      this.pushArr(e.target.innerHTML)
      this.add(1)
      this.getDatas({
        total: this.sumData,
        list: this.arrData
      }) 
    }
  },
  mounted:function(){
    console.log( this.objData )       // { b:2 }
    console.log( this.arrData )       // ["a"]
    console.log( this.sumData )       // 1
    this.getDatas({a:1})           
    this.pushArr("aaa")           
    this.add(9)    
    console.log( this.objData )       // { a:1 }
    console.log( this.arrData )       // ["a","aaa"]
    console.log( this.sumData )       // 10
  }
}
</script>

2.模块化 modules 高级使用

      组件中引入 mapGetters、mapActions 和 mapStates的使用

在大多数的项目中,我们对于全局状态的管理并不仅仅一种情况的需求,有时有多方面的需求,比如写一个项目,你所用到的全局的state可能是page1.vue这一块儿的,也有可能是page2.vue这一块儿的;像这样的情况我们就要考虑使用vuex中的 modules 模块化的高级使用方法了,使用如下:

<template>
  <div class="test">
    <button @click="push">拖鞋</button>
    <button @click="push">上衣</button>
    <button @click="push">帽子</button>
    <p>所有物品:{{ arrData }}</p>
    <p>总件数:{{ sumData }}</p>
    <p>总信息:{{ objData }}</p>
  </div>
</template>

<script>
import { mapState, mapGetters, mapActions } from 'vuex'
export default {
  data () {
    return {
    }
  },
  computed:{
    //(-----1.使用 mapState 来获取 state 对象中的数据,不推荐使用-----)
    /*
    ...mapState({                   
      objData:state=>state.obj,        // 获取 store/index.js 中 state 对象中的 obj
      arrData:state=>state.page1.arr,  // 获取 store/module/page1.js 中 state 对象中的 arr
      sumData:state=>state.page2.sum   // 获取 store/module/page2.js 中 state 对象中的 sum
    }),
    */

    //(-----2.使用 mapGetters 来获取 getters 对象中的方法(该方式获取state中的值比上面方式更理想),推荐使用-----)
    ...mapGetters({              
      objData:'obj',                   // 获取 store/index.js 中 getters 对象中的 obj 方法  
      arrData:'page1/getArr',          // 获取 store/module/page1.js 中 getters 对象中的 getArr 方法
      sumData:'page2/getSum'           // 获取 store/module/page2.js 中 getters 对象中的 getSum 方法 
    })
  },
  methods:{ 
    //(-----3.使用 mapActions 来获取 actions 对象中的方法-----)
    ...mapActions({             
      newObjRun:'obj',                 // 获取 store/index.js 中 actions 对象中的 obj方法 
      pushArrRun:'page1/pushArrRun',   // 获取 store/module/page1.js 中 actions 对象中的 pushArrRun 方法
      addTo:'page2/addTo'              // 获取 store/module/page2.js 中 actions 对象中的 addTo 方法    
// 组件中的方法名可以随便取,并且可以在当前组件中随处调用,但是被赋值的方法,要跟store 中的 actions 对象里面的方法名一直   
    }),
    push(e){
      this.pushArrRun(e.target.innerHTML) 
      this.addTo(1)
      let _this = this
      this.newObjRun({
        total: this.sumData,
        list: this.arrData
      })  
    }
  },
  mounted(){
    console.log( this.objData )       // { b:2 }
    console.log( this.arrData )       // ["a"]
    console.log( this.sumData )       // 1
    this.newObjRun({a:1})           
    this.pushArrRun("aaa")           
    this.addTo(9)    
    console.log( this.objData )       // { a:1 }
    console.log( this.arrData )       // ["a","aaa"]
    console.log( this.sumData )       // 10
  }
}
</script>

 通过上面的模块化高级用法 用法举例,咱再来简单的梳理一下使用方法

1.获取 某个状态的值:   

...mapGetters({              
      objData:'obj',               // 获取 store/index.js 中 getters 对象中的 obj 方法  
      arrData:'page1/getArr',      // 获取 store/module/page1.js 中 getters 对象中的 getArr 方法
      sumData:'page2/getSum'       // 获取 store/module/page2.js 中 getters 对象中的 getSum 方法 
})

2.设置 某个状态的值: 

1.在组件钩子函数 methodes 中导入函数,导入的函数,并分别赋值给自定义的一个变量名。这些函数就相当于在methodes中定义的函数一样,可在组件任意地方调用和传值。
methodes:{
    ...mapActions({             
      newObjRun:'obj',                 // 获取 store/index.js 中 actions 对象中的 obj方法 
      pushArrRun:'page1/pushArrRun',   // 获取 store/module/page1.js 中 actions 对象中的 pushArrRun 方法
      addTo:'page2/addTo'              // 获取 store/module/page2.js 中 actions 对象中的 addTo 方法         
    }),

}


2.当前组件中使用
<template> 
    <button @click="addTo(9)"> // 设置 page2 中 Sum 的值
</template>  
...

mounted(){ // 钩子函数中使用
    this.addTo(9)  // 设置 page2 中 Sum 的值
} 

OK 关于Vuex 的基本用法先介绍到这,非常适合初学者。有什么更好的用法,欢迎留言讨论

vue 完整项目配置1(下载/安装)

vue项目配置2-项目目录结构,vue打包白屏,图片加载不出等问题

vue项目配置3-router路由配置,元信息meta的使用-登录拦截验证

vue项目配置5-axios请求 配置​​​​​​​

猜你喜欢

转载自blog.csdn.net/qq_41772754/article/details/88074103