vuex使用总结(简单易懂)

39 篇文章 20 订阅

参考文档:
Vuex Guide
在这里插入图片描述

1.基础知识

  • vuex用来帮助我们管理共享状态

  • 状态是一种短暂存储在内存堆栈的数据,一旦刷新网页,如果不做维护的话,状态将全部消失

  • 使用状态的优点是,能够实时响应变化,源状态改变,其他使用该状态的组件中的引用状态将同步变化

  • 每一个 Vuex 应用的核心就是 store(仓库),它是一个包含着你的应用中大部分的状态 (state)的容器

  • Vuex 和单纯的全局对象有以下两点不同:Vuex 的状态存储是响应式的;改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation

  • store最核心的两个概念是state 和mutations,前者定义状态,后者改变状态,通过 store.state 来获取状态对象,并通过 store.commit 方法触发状态变更

  • store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅需要在计算属性中返回即可。触发变化也仅仅是在组件的 methods 中提交 mutation。

  • 存储在 Vuex 中的数据和 Vue 实例中的 data 遵循相同的规则:状态对象必须是纯粹的对象 (含有零个或多个的 key/value 对)

  • Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态

  • vuex中的方法或者属性映射到某个组件上中:同名映射传字符串数组,不同名映射传对象

2. 使用Vuex(单状态树)

  1. 项目中导入依赖 npm install vuex@3 --save,注意这个版本需要与Vue的版本对应
  2. 创建store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
//将 store 实例作为插件安装
Vue.use(Vuex);
//对外暴露store类的一个实例
export default new Vuex.Store({
    state: {
        userInfo: {
            userName: ''
        }
    },
    mutations: {
        userInfo(state, userInfo) {
            state.userInfo = userInfo
        }
    },
})
  1. main.js中注册
import store from './store';
new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

3.State(声明状态)

  1. 在store中声明状态
    对象{key:value},对象数组[],字符串,数字
  2. 在 Vue 组件中获得 Vuex 状态
    假设vuex的state中声明了一个count状态,在组件中获取这个count状态:
  computed: {
    count () {
      return this.$store.state.count
    }
  }

或者使用mapState 辅助函数获取这个count状态(对于一个组件需要获取多个状态的情况特别方便):
映射出来起个别名,传键值对,别名是键,仓库中的名是字符串值

computed: {
  localComputed () { /* ... */ },
  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    // ...
  })
}

不起别名的话,直接传字符串

computed: {
  localComputed () { /* ... */ },
  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState([
    // ...
  ])
}

4.Mutation(同步修改)

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。mutation 必须是同步函数,里面不能出现回调函数,就是说方法体执行完成后,状态就会直接发生变化,配合action理解比较好这个。

假设,mutation中存在两个异步操作,并且假设它们都对同一个状态进行直接修改,但是由于它们是互为异步操作,我们不能知道它们中谁会先执行完成,所以对于状态的修改结果我们无法知道,为了方便跟踪状态变化,我们不允许在mutation中有异步回调

每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler),其中回调函数会接受 state 作为第一个参数
mutation 事件类型说白了就是方法名,回调函数就是方法体,state 是方法的第一个参数

mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }

可以向 store.commit 传入额外的参数,即 mutation 的载荷(payload)

mutations: {
  increment (state, n) {
    state.count += n
  }
}

在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读:

// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

通过commit的形式唤醒一个 mutation 处理函数

//无参
store.commit('increment')
//普通带参
store.commit('increment',10)
//参数对象化
store.commit('increment', {
  amount: 10
})

对象风格的提交方式:
处理函数:

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit({
  type: 'increment',
  amount: 10
})

在组件中提交 Mutation:

  1. 使用 this.$store.commit(‘xxx’) 提交 mutation
  2. 使用mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用
 methods: {
    ...mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
      // `mapMutations` 也支持载荷
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
    ]),
    ...mapMutations({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
  }

5.Action(异步修改)

Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作

actions: {
    increment (context) {
      context.commit('increment')
    }
  }

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。当我们在之后介绍到 Modules 时,你就知道 context 对象为什么不是 store 实例本身了。
实践中,用参数解构来简化代码(特别是我们需要调用 commit 很多次的时候):

actions: {
  increment ({ commit }) {
    commit('increment')
  }
}

Action 通过 store.dispatch 方法触发:store.dispatch('increment')
不同于mutation 必须同步执行的限制,我们可以在 action 内部执行异步操作:
Actions 支持同样的载荷方式和对象方式进行分发
在组件中分发 Action:
1.使用 this.$store.dispatch(‘xxx’) 分发 action
2.使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}

6.Getter(派生状态)

从 store 中的 state 中派生出一些状态
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。
Getter 接受 state 作为其第一个参数
Getter 会暴露为 store.getters 对象,你可以以属性的形式访问这些值
Getter 也可以接受其他 getter 作为第二个参数
在任何组件中使用它:this.$store.getters.属性名
你也可以通过让 getter 返回一个函数,来实现给 getter 传参。在你对 store 里的数组进行查询时非常有用。
mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:

 computed: {
  // 使用对象展开运算符将 getter 混入 computed 对象中
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }

如果你想将一个 getter 属性另取一个名字,使用对象形式:

...mapGetters({
  // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
  doneCount: 'doneTodosCount'
})

7.总结

  • vuex共享状态管理,在我看来一个最大的优点是一个组件的数据变化了,可以同步引起另一个组件数据的变化,这对于SPA是非常好的特性

  • 仓库和组件间存在映射关系:state和getters都是映射到组件的计算属性中,而actions和mutations都是映射到组件的方法中

  • 通过 …mapXXX(数组/对象) 来与组件的原有方法或计算属性进行混合挂载,然后直接通过this来访问,this指的是当前组件实例对象

  • 对于使用…mapXXX有两种情况:
    要是想直接用仓库中的名字来挂载到组件实例上,我们传递一个字符串数组,字符串是名字
    要是想给仓库中的名字取一个别名,然后再挂载到组件实例上,我们传键值对类型的对象,键是别名,值是仓库中的名

  • 也可以不做映射,直接使用已经注入挂载到组件的this.$store 对象来访问仓库中的属性和方法,this指的是当前组件实例对象
    具体是:

this.$store.state.属性名

this.$store.commit(‘mutation类型名’,载荷对象)

this.$store.getters.属性名/方法名

this.$store.dispatch(‘action类型名’,载荷对象)

  • state和mutation核心概念,而getter和action分别是它们的衍生概念

8.感悟

我觉得程序员是一个需要经常学习的群体,应当追随“时尚”,如何学习一门新技术呢?我的经验是按照如下步骤进行认识迭代:

  1. 刚刚接触新技术的话,去看官方文档你可能看不懂,如果可以看懂,最好就从官方文档中学习总结和实践,看不懂可以借助一些视频网站跟随先行者进行学习,强调要边学边练
  2. 有了一定的技术基础的话,可以在做一个项目练手,在这中间,最好把在使用新技术的过程中有的理解以及遇到的问题,以及如何解决这个问题的步骤整理记录下来,可以分享出来,我的感悟是,当你试图学习和理解一个东西时,你可以试图去想象你是一个老师,你会如何去教那些不会这个技术的人呢,你会怎样组织你的语言去理解和描述它呢,当你试图用你的知识做输出时,你很快就会发现自己的问题,善用搜索引擎是解决这中间产生问题的好办法,这就是所谓的教学相长吧!
  3. 做个一个项目后,你会发现许多问题,这时候,官方文档又一次出现了,第一次看不懂,现在有了理解后,再来拜访一下,学习总结一下,你会有了更好的理解和系统化的知识框架了。
  4. 如哲学所说:人的认识发展是一个不断随实践的深入而螺旋上升的过程,我们现在只需要在看文档和做项目间循环往复进行认识迭代即可
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值