Vue.js学习笔记(六)(Vuex)

在这里插入图片描述

  • 思考:为什么Vue Components不与Mutations直接相连
  • 原因: Mutations每个方法完成的事件要尽可能单一,devtools无法监听mutations方法内的多个操作,但是actions可以提交多次给Mutations,所以进行多个操作时,先在actions里进行多个操作,在Actions里将多个操作拆分成一个一个操作发送给mutations

1.Vuex的基本使用


  • 介绍:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
  • 意义:比如一个项目中要共享某一个状态,用户id,用户头像等,这些信息可以统一管理起来,做全局变量
  • 基本使用步骤
    • 第一步:和vue-router一样先创建一个index.js并且调用 Vue.use(Vuex)
    • 第二步:创建Vuex实例并传入state/mutations等参数(state传参数,mutation传调用函数)
    • 第三步:在Vue实例(main.js中)中挂载创建的Vuex实例
    • 第四步:在组件中使用调用函数
    • 第五步:前往devtools查看状态的改变
  • 代码:
index.js:
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const store = new Vuex.Store({
    
    
  state: {
    
    
    counter: 6666
  },
  mutations: {
    
    
    inc(state){
    
    
      state.counter++;
    },
    dec(state){
    
    
      state.counter--;
    }
  }
});

export default store;

App.vue:
<template>
  <div id="app">
    <h2>counter:{
    
    {
    
    $store.state.counter}}</h2>
    <button @click="add">+</button>
    <button @click="sub">-</button>
  </div>
</template>

<script>
export default {
    
    
  name: 'App',
  methods: {
    
    
    add(){
    
    
      this.$store.commit("inc");
    },
    sub(){
    
    
      this.$store.commit("dec");
    }
  }
}
</script>
  • 效果:
    -

在这里插入图片描述
可以正常+/-,devtools也正常检查

2.State单一状态树

引用王红元老师的一段话:

  • 我们知道,在国内我们有很多的信息需要被记录,比如上学时的个人档案,工作后的社保记录,公积金记录,结婚后的婚姻信息,以及其他相关的户口、医疗、文凭、房产记录等等(还有很多信息)。这些信息被分散在很多地方进行管理,有一天你需要办某个业务时(比如入户某个城市),你会发现你需要到各个对应的工作地点去打印、盖章各种资料信息,最后到一个地方提交证明你的信息无误。
  • 如果你的状态信息是保存到多个Store对象中的,那么之后的管理和维护等等都会变得特别困难。所以Vuex也使用了单一状态树来管理应用层级的全部状态。单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。

3.Vuex-getters的使用


  • 介绍:getters和state的关系类似于 data和computed ,更复杂的属性
  • 案例:state中有一个学生数组,要显示其中年龄大于20的学生,还要显示其中大于自己定义年龄的学生
  • 代码:
index.js:
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const store = new Vuex.Store({
    
    
  state: {
    
    
    student:[
      {
    
    id: 110, name: 'jjj', age: 18},
      {
    
    id: 111, name: 'ffffe', age: 24},
      {
    
    id: 112, name: 'sss', age: 30},
      {
    
    id: 113, name: 'rrry', age: 10}
    ]
  },
  getters: {
    
    
    more20stu(state){
    
    
      return state.student.filter(student => student.age > 20);
    },
    moreAgeStu(state){
    
    
      return age => {
    
    
        return state.student.filter(student => student.age > age);
      }
    }
  }
});

export default store;

App.vue:
<template>
  <div id="app">
    <h2>student:{
    
    {
    
    $store.getters.more20stu}}</h2>
    <h2>student:{
    
    {
    
    $store.getters.moreAgeStu(8)}}</h2>
  </div>
</template>
<script>


export default {
    
    
  name: 'App',
}
</script>
  • 结果 :
    -
  • 总结:当属性需要运算再显示的时候就使用getters

4.mutations


  • 介绍:Vuex的store状态的更新唯一方式:提交Mutation
  • 用法:mutations传递可以参数,还有两种提交风格
  • 普通方式提交代码:
App.vue
<button @click="addCount(5)">+5</button>
<button @click="addStudent()">加入学生</button>
addCount(count){
    
    
      this.$store.commit({
    
    
        type: "addCount",
        count
      })
    },
    addStudent(){
    
    
      let student = {
    
    id: 114, name: "114fff", age: 18};
      this.$store.commit("addStudent", student);
    }
  • 第二种风格方式提交代码:
App.vue
<button @click="addCount(5)">+5</button>
    addCount(count){
    
    
      //method2
      this.$store.commit({
    
    
        type: "addCount",
        count
      })
    }
index.js:
  mutations: {
    
    
    addCount(state, payload){
    
    
      console.log(payload);
      state.counter += payload.count;
    }
  },
  • 打印结果:
    在这里插入图片描述

5.Mutation响应规则

Vuex的store中的state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新,若要达到响应式效果,提前在store中初始化好所需的属性,没有初始化的属性要达到响应式,需要采取特殊方法

  • 未初始化的属性要达到响应式的写法:
  • 代码:
index.js:
const store = new Vuex.Store({
    
    
  state: {
    
    
    info: {
    
    
      id: 8888,
      name: "Helen",
      age: 99
    }
  },
  mutations: {
    
    
    updateInfo(state){
    
    
      //method1 :非响应式
      state.info["extra"] = "extraInfo";
      
      //method2: 响应式
      Vue.set(state.info, 'extra', "extraInfo")
    }
  }
});
  • 非响应式结果:
    在这里插入图片描述
  • 响应式结果:
    在这里插入图片描述

6.actions

  • 介绍:Action类似于Mutation, 但是是用来代替Mutation进行异步操作的
  • 意义:Mutation中可以进行异步操作,但是devtools中无法监听异步操作,想要devtools监听异步操作,先经过actions再commit给mutations
  • context:context是和store对象具有相同方法和属性的对象
  • 代码样例:
App.vue
    updateInfo(){
    
    
      this.$store.dispatch({
    
    
        type: "aUpdateInfo",
        message: "我是payload里面一个默默无闻的message",
        success: () => {
    
               //设置一个回调函数,执行完commit就调用
          console.log("我是一个App.vue里的回调函数success");
        }
      })
    }
    
index.js:
const store = new Vuex.Store({
    
    
  state: {
    
    
    info: {
    
    
      id: 8888,
      name: "Helen",
      age: 99
    }
  },
  mutations: {
    
    
    updateInfo(state){
    
    
      state.info.age = 18;
    }
  },
  actions: {
    
    
    aUpdateInfo(context, payload) {
    
    
      setTimeout(() => {
    
    
        context.commit("updateInfo");
        console.log(payload.message);
        payload.success();   //设置一个回调函数,执行完commit就调用
      }, 1000)
    }
  }
});
  • 结果: 在这里插入图片描述
  • 更优秀的回调方法(Promise)
index.js:
  actions: {
    
    
    aUpdateInfo(context, payload) {
    
    
      return new Promise((resolve) => {
    
    
        setTimeout(() => {
    
    
          context.commit("updateInfo");
          resolve("我是resolve里的内容");
        }, 1000)
      });
    }
  }
App.vue:
    updateInfo(){
    
    
      this.$store
        .dispatch({
    
    
        type: "aUpdateInfo",
      })              //this.$store.dispatch相当于aUpdateInfo函数中return的promise
        .then(res => {
    
    
          console.log(res);
        })
    }

7.modules

  • 介绍: Vue使用单一状态树,那么也意味着很多状态都会交给Vuex来管理,Vuex允许我们将store分割成模块(Module), 而每个模块拥有自己的state、mutations、actions、getters,这样来避免store臃肿
  • 用法:除了调用state外,其余用法和store主体一样,getters,mutations,actions所调用的state,context不会调用到store主体,只会在自身模块里调用,想要调用主体用rootState,rootGetters
  • 案例:
index.js
const moduleA = {
    
    
  state: {
    
    
    messageA: "我是moduleA中的message"
  },
  mutations: {
    
    
    updateMessageA(state, payload){
    
    
      state.messageA = "6666666666666666"+ payload;
    }
  },
  getters: {
    
    
    aGetTest(state){
    
    
      return state.messageA + "aGetTest";
    },
    aGetTest2(state, getters){
    
    
      return getters.aGetTest + "222222222";
    }
  },
  actions: {
    
    
    asyncUpdateMessageA(context){
    
    
      setTimeout(() => {
    
    
        context.commit("updateMessageA", "我是异步操作的payload")
      }, 1000)
    }
  }
};
const store = new Vuex.Store({
    
    
  modules: {
    
    
    a: moduleA
  }
});

App.vue:
    <p>-------------------探究modules---------------------</p>
    <h2>messageA:{
    
    {
    
    $store.state.a.messageA}}</h2>
    <h2>getter测试:{
    
    {
    
    $store.getters.aGetTest}}</h2>
    <h2>getter2测试:{
    
    {
    
    $store.getters.aGetTest2}}</h2>
    <button @click="updateMessageA">测试moduleA-mutations</button>
    <button @click="asyncUpdateMessageA">测试moduleA-actions</button>

    updateMessageA(){
    
    
      this.$store.commit("updateMessageA", "我是payload");
    },
    asyncUpdateMessageA(){
    
    
      this.$store.dispatch("asyncUpdateMessageA");
    }
  • 同步操作效果展示:
    在这里插入图片描述
  • 异步操作效果展示:
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43249043/article/details/107334678