Vuex的学习

终于又开始学习了!
最近有点瞎忙,哎!


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

1. vuex的使用场景是什么呢?
  • 一般来讲,小的单页面应用开发程序不适合使用Vuex,因为还是有点繁琐的。所以,vuex还是比较适合比较大型的单页面应用程序的开发。
  • 使用场景,就是全局的变量管理,比如登录的token,以及一些用户信息什么的,很多地方都会使用到,就比较适合全局管理。
  • 官方解释:
    • 多个视图依赖于同一状态(例如兄弟组件传值)。
    • 来自不同视图的行为需要变更同一状态(例如父子组件传值)。
  • 还有其他的使用的时候有体会再总结吧!

下面开始介绍怎么使用吧
(就不从基础的开始介绍了吧,直接将store单独抽离出来一个文件开始吧)


使用vue-cli搭建的项目目录结构

可以看出store文件下面有新建了几个js文件,是什么意思呢?

  • index.js 是总的状态管理文件
  • app.js/ user.js 是分模块的状态管理
  • mutation-types.js 是常量集合文件

相当于流程:
index.js文件里导入 app.js/user.js等不同模块,再将这一系列的模块挂载到store对象中。再在 main.js文件里导入 store文件,就可以全局管理了,这样也使状态管理更加清晰。

2. vuex的开始与核心概念:
  • 首先创建一个store对象
const store = new Vuex.Store({
  state: {
     count:0
  },
  getters:{
     myCount(state){
          return `当前数字是:${state.count}`
      }
  },
  mutations: { 
     increment(state){ 
        state.count += 1;
      }  
  },
  actions:{
      myIncrease(context){
        context.commit(increment)
      }
  }
})

可以看出去这个对象包含了四个属性,分别是干什么的呢?

  • state:就是需要全局管理的状态,一般通过this.$store.state.变量名来获取其值,一般写在computed计算属性中。
    即在根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到。

  • getters: 就是对全局的状态做个处理,比如过滤等操作,可认为是state的计算属性,一般写在computed 计算属性中。
    getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算
    一般通过this.$store.getters.方法名来调用其中的方法,getters 接受 state 作为其第一个参数

  • mutations: 改变全局状态的操作(唯一方法),一般写在methods中。
    记住:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,它会接受 state 作为第一个参数。
    一般通过this.commit('increment')来调用mutations中的方法

  • actions: 改变状态的复杂业务逻辑,一般写在methods中。
    action提交的是 mutation,而不是直接变更状态。
    action可以包含任意异步操作
    action 函数接受一个与 store 实例具有相同方法和属性的 context对象,可以调用 context.commit 提交一个 mutation,也可通过 context.statecontext.getters 来获取 state 和 getters。

其实取值可以使用官方文档的辅助函数mapState,mapGetters,mapMutations,mapActions,操作更加简单。


前面的这些 自己总结加上官方的说法,理解之后再看下面的操作,建议去看官方文档

3. store文件分模块抽离

直接上文件内容分析(计算器为例):

index.js :总的模块整合,导入到store对象上

  • 记住要先引入vue和vuex
  • 再引入分离的模块
  • 最后将分离的模块统一引入sotre对象中,通过modules属性
import Vuex from "vuex";
import Vue from "vue";
//引入 分离的模块
import app from './app';
import user from './user';
Vue.use(Vuex);
// 分模块管理
const store = new Vuex.Store({
  modules:{
    app,
    user
  }

});
export default store

下面看看分离的app.js文件,单独写某个模块的全局状态管理(user.js同)

  • 可看出创建了一个app对象,里面包含了store的四个属性,为了可以直接引入到store对象中。
  • 里面还引入了mutation-types文件,也就是将变量名替换成常量名。因为方法名在组件中使用时,要写成字符串格式,不太方便。
  • mutations和actions属性包含的方法,除了接收的固定参数,也可接收传参
常量集合里面获取的名字  进行 替换调用字符串的名字
import {Increment,Decrement} from './mutation-types';
const app = {
  state:{
    count:0
  },
  getters:{
    myCount(state){
      return `当前数字是:${state.count}`
    }
  },
  mutations:{
    方括号 引入常量代表的变量方法名
    [Increment](state,n){  方法都可传参
      state.count += n;
    },
    [Decrement](state,n){
      state.count -= n;
    }
  },
  actions:{
    myIncrease(context,obj){
      context.commit(Increment,2);方法可传参
    },
    myDecrease(context){
      context.commit(Decrement,2);
    }
  }
};
export default app

在index.js文件中导入了app.js,再在store对象中引入app模块,相当于整个状态管理全部集中在index.js文件,所以要全局使用的话,还需要将store对象引入到 main.js文件中,并挂载到Vue实例上

main.js文件

import Vue from 'vue'
import Vuex from 'vuex'
import App from './App'
import router from './router'
import store from './store'
Vue.config.productionTip = false;
Vue.use(Vuex);
new Vue({
  el: '#app',
  components: { App },
  template: '<App/>',
  router,
  store,
});

最后看下,常量集合文件mutation-types.js,就是将全局的变量名,可以统一命名成常量名。导入这个文件,则名字就可以全局规范,提高代码的可读性

例如规范了 两个函数的名字
export const Increment= "increment";
export const Decrement= "decrement";


4.组件中具体使用 (计数器)
  • 可看出使用了辅助函数mapState,mapGetters,mapMutations,mapActions,使用es6的扩展运算符,直接展开数组,每个属性都有一个辅助函数。
  • 导入了 mutation-types,常量集合文件,引用时可以不用字符串
    ...mapMutations([Increment,Decrement]) 使用写法
    ...mapActions(['myIncrease','myDecrease']) 未使用写法
  • 注释部分,调用store中mutation中的方法,改变全局状态,其实实现的功能是一样的:
    • 方法(1):this.$store.commit('increment');
    • 方法(2):映射store中的方法,并直接调用(推荐)
      import {mapMutations} from 'vuex';
      this.increment();
    • 方法(3):this.$store.state.count += 1;
      直接修改 state 里面的值 ,但不会产生mutation的记录(不推荐)
    • 方法(4):在actions中调用mutations中改变状态的方法,然后在组件中可直接调用actions中的方法:
      先在store中action 调用:increase(context){ context.commit(Increment,2); }
      再在组件中调用: this.myIncrease()
  • state 分模块管理之后 得写映射 (注意写法,此时是 state.app.变量名)
    ...mapState({ count:state =>{ return state.app.count } })
<template>
  <div id="app">
    <h1>{{count}}</h1>
    <h3>{{myCount}}</h3>
    <button @click="increase">增加</button>
    <button @click="decrease">减少</button>
    <router-view/>
  </div>
</template>

<script>
import {mapState} from "vuex";
import {mapGetters} from 'vuex';
import {mapMutations} from 'vuex';
import {mapActions} from 'vuex';
import {Increment,Decrement} from '@/store/mutation-types'

export default {
  name: 'App',
  computed:{
    1.分类管理之前
     ...mapState(['count']), //展开数组
     ...mapGetters(['myCount']),

    2.state 分模块管理之后 得写映射 
    ...mapState({
        count:state =>{
          return state.app.count
       }
    })
  },
  methods:{
    //...mapMutations(['increment','decrement']),
    ...mapMutations([Increment,Decrement]),
    ...mapActions(['myIncrease','myDecrease']),
    increase(){
      // this.$store.commit('increment');
      // this.increment();
      //直接修改 state 里面的值   不会产生mutation的记录
      // this.$store.state.count += 1;
      this.myIncrease({id:123});  // 可传参
    },
    decrease(){
      // this.decrement();
      this.myDecrease()
    }
  }
}
}
</script>


最后看下效果,也感受一下,全局状态管理的舒服感,始终要记得:** Vuex 的 store 中的状态的唯一方法是提交 mutation**,所以官方提供的浏览器插件Vue,就可清晰的记录每次mutation的结果。


每次加2,减少2,四次加,两次减

mutation记录了每次的操作

这就是最终的结果了,看视频学的,也看了一些官方文档,因为写项目的时候还没学这些,所以那些需要全局使用的信息,都存在了 localStorage中,这也是个方法,但是数据也不能存储太多,操作起来也不是太方便。
学了vuex也比较浅显,也没实际的在项目中使用过,也不太能体会它的优点,反而感觉有点繁琐,也许真正的使用了,才能体会到它的好处吧。

学无止境,苦海无涯!
今天的学习到此结束,下次不知道啥时候见了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容