文章目录
- vuex概述
- 构建vuex[多组件数据共享]环境
- 创建一个空仓库
- ps.创建仓库时遇到的错误
- 核心概念 - state状态
- 核心概念 - mutations
- 辅助函数 - mapMutations
- 核心概念 - actions
- 辅助函数 - mapActions
- 核心概念 - getters
- 核心概念 - 模块module(进阶语法)
vuex概述
vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
状态管理模式:把组件的共享状态抽取出来,以一个全局单例模式管理。这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为。
通俗来讲:vuex是一个vue的状态管理工具,状态就是数据。(vuex是一个插件,可以帮我们管理vue通用的数据)。
场景:
- 某个状态在很多组件来使用(个人信息)
- 多组件共讨那个维护一份数据(购物车)
优势:
- 共同维护一份数据,数据集中化管理
- 响应式变化
- 操作简洁(vuex提供了一些辅助函数)
构建vuex[多组件数据共享]环境
目标:基于脚手架创建项目,构建vuex多组件数据共享环境。
效果:多个组件共享一份数据
- 任意一个组件都可以修改数据
- 三个组件的数据是同步的
创建一个空仓库
目标:安装vuex插件,初始化一个空仓库
- 安装vuex:
npm i vuex@3
(vue2对应vuex3,vue3对应vuex4) - 新建store/index.js专门存放vuex
- Vue.use(Vuex)创建仓库new Vue.Store()
- 在main.js中导入挂载到Vue实例上
ps.创建仓库时遇到的错误
如果安装vuex时出现如上错误,可以通过命令行npm i vuex@3 --legacy-peer-deps
尝试安装。
出现这个问题的原因大概是因为node的版本太高,或者是npm版本不对。
通过在App.vue中打印this.$store
来查看仓库是否创建成功,如果打印的是undefined,则仓库创建失败。
核心概念 - state状态
-
提供数据:
State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储。在state对象中可以添加我们要共享的数据。
const store = new Vuex.Store({ state: { count: 101 } })
-
使用数据:
-
通过store直接访问
获取store
(1)this.$store
(2)import导入store
模板中:{{ $store.state.xxx }}
组件逻辑中:this.$store.state.xxx
JS模块中:store.state.xxx
-
通过辅助函数(简化)
mapState是辅助函数,帮助我们把store中的数据自动映射到组件的计算属性中。
-
核心概念 - mutations
目标:明确vuex同样遵循单向数据流,组件中不能直接修改仓库的数据。
this.$store.state.count++
是错误的写法,有时虽然能运行成功,但项目大起来后很难维护,我们很难找到仓库的数据在哪里被修改。这个错误vue默认不会监测,因为监测需要成本。
通过
strict: true
可以开启严格模式,有利于初学者写代码,上线时需要关闭,因为它会消耗运行性能。
目标:掌握mutations的操作流程,来修改state数据。(state数据的修改只能通过mutations)
-
定义mutations对象,对象中存放修改state的方法
const store = new Vue.Store({ state: { count: 0 }, mutations: { addCount (state, n) { this.state.count += n } } })
-
组件中提交调用mutations
this.$store.commit('addCount', n)
注意:mutations参数有且只能有一个,如果需要多个参数,包装成一个对象。
辅助函数 - mapMutations
mapMutations和mapState很像,它是把位于mutations中的方法提取了出来,映射到组件methods中。
mutations: {
subCount (state, n){
state.count -= n
},
}
import { mapMutations } from 'vuex'
methods: {
...mapMutations(['subCount'])
}
this.subCount(10) // 调用
相当于:
methods: {
subCount (n) {
this.$store.commit('subCount', n)
},
}
核心概念 - actions
目标:明确action的基本语法,处理异步操作。
说明:mutations必须是同步的(便于监测数据变化,记录调试)
-
提供action方法
mutations: { changeCount (state, newCount) { state.count = newCount } }
actions: { aetAsyncCount (context, num) { setTimeout(() => { context.commit('changeCount', num) }, 1000) } }
-
页面中调用dispatch调用
this.$store.dispatch('setAsyncCount', 200)
辅助函数 - mapActions
mapActions是把位于actions中的方法提取出来,映射到组件methods中。
actions: {
aetAsyncCount (context, num) {
setTimeout(() => {
context.commit('changeCount', num)
}, 1000)
}
}
import { mapActiosn } from 'vuex'
methods: {
...mapActions(['changCountAction'])
}
this.changeCountAction(99) // 调用
核心概念 - getters
除了state之外,有时我们还需要从state中派生出一些状态,这些状态是依赖state的,此时会用到getters(getters类似于计算属性)。
例如:state中定义了list为1-10的数组,需要显示所有大于5的数据。
-
定义getters
getters: { filterList (state) { return state.list.filter(item => item > 5) } }
-
访问getters
-
通过store访问getters
{{ $store.getters.filterList }}
-
通过辅助函数mapGetters映射
computed: { ...mapGetters(['filterList']) }
-
核心概念 - 模块module(进阶语法)
由于vuex使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store对象很有可能变得相当臃肿,难以维护。
模块拆分:
user模块:store/modules/user.js
const state = {
userInfo: {
name: 'zs',
age: 18
}
}
const mutations = {}
const actions = {}
const getters = {}
export default {
state,
mutations,
actions,
getters
}
import user from './modules/user'
const store = new Vuex.Store({
modules: {
user
}
})
使用模块中的数据:
-
直接通过模块名访问:
$store.state.模块名.xxx
$store.getters['模块名/xxx']
$store.commit('模块名/xxx', 额外参数)
$store.dispatch('模块名/xxx', 额外参数)
-
通过mapState映射
默认根级别的映射:
mapState(['xxx'])
mapGetters(['xxx'])
mapMutations(['xxx'])
mapActions(['xxx'])
子模块的映射:
mapState('模块名', ['xxx'])
mapGetters('模块名', ['xxx'])
mapMutations('模块名', ['xxx'])
mapActions('模块名', ['xxx'])
-
需要开启命名空间:
export default { namespaced: true, // 开启命名空间 state, mutations, actions, getters }
-
默认模块中的mutation和actions会被挂载到全局,需要开启命名空间,才会挂载到子模块。