1.基本概念
vuex是什么?
vuex 是vue的状态管理工具,状态即数据
大白话:vuex 是一个插件,可以帮我们管理 vue中通用的数据 (多组件共享的数据)
优势:
① 共同维护一份数据,数据归一化管理
② 响应式变化
③ 操作简洁 (vuex提供了一些辅助函数)
vuex 的使用 - 创建仓库
与vue-router类似,vuex是一个独立存在的插件,如果脚手架初始化没有选 vuex,就需要额外安装。
npm i vuex@3
2 新建 store/index.js
专门存放 vuex
为了维护项目目录的整洁,在src目录下新建一个store目录其下放置一个index.js文件。 (和 router/index.js
类似)
// 导入 vue
import Vue from 'vue'
// 导入 vuex
import Vuex from 'vuex'
// vuex也是vue的插件, 需要use一下, 进行插件的安装初始化
Vue.use(Vuex)
// 创建仓库 store
const store = new Vuex.Store()
// 导出仓库
export default store
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store
}).$mount('#app')
此刻起, 就成功创建了一个 空仓库!!
Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。
如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式(opens new window)就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。引用 Redux 的作者 Dan Abramov 的话说就是:
2.state(状态)
通过上面已经准备好了一个空仓库,那么如何给仓库提供数据呢?
State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储。
在 state 对象中可以添加我们要共享的数据。
共享数据已经准备好了,如何访问它呢
1通过 store 直接访问
2通过辅助函数mapState来访问 (简化)
1. 通过 store 直接访问
2.mapState
mapState是辅助函数,帮助我们把store中的数据映射到 组件的计算属性中, 它属于一种方便的用法
用法 :
import { mapState } from 'vuex'
computed: {
...mapState(['count'])
}
/*
上面代码等价于
computed: {
count () {
return this.$store.state.count
}
}
*/
<div> state的数据:{{ count }}</div>
2.Mutations(同步方法)
核心概念
vuex 建议我们组件中不直接修改仓库的数据,想要修改数据我们统一通过vuex提供的mutations来进行
state数据的修改只能通过 mutations ,并且mutations中必须写同步代码,ajax请求,setTimout等不应该放到mutations中
好处:数据的修改被vuex集中管理,提高对数据管理的有效性
1.通过 commit 提交
const store = new Vuex.Store({
state: {
count: 0
},
// 定义mutations
mutations: {
// 方法里参数 第一个参数是当前store的state属性(固定写死)
// 第二个参数count(可以自定义) 运输参数 调用mutaiions的时候 可以传递参数 传递载荷
addCount (state,count) {
state.count += count
}
},
})
this.$store.commit('addCount',1)
2.mapMutation
mapMutations和mapState很像,它把位于mutations中的方法提取了出来,我们可以将它导入
import { mapMutations } from 'vuex'
methods: {
...mapMutations(['addCount'])
}
/*
上面代码的含义是将mutations的方法导入了methods中,等价于:
methods: {
// commit(方法名, 载荷参数)
addCount (count) {
this.$store.commit('addCount',count)
}
}
*/
<button @click="addCoun(1)">值+1</button>
注意: Vuex中mutations中要求不能写异步代码,如果有异步的ajax请求,setTimout等应该放置在actions中
3.Actions(异步方法)
1.通过dispatch派发
state是存放数据的
mutations是同步更新数据
actions则负责进行异步操,如果有异步的ajax请求,setTimout等应该放置在actions中
需求: 1秒钟之后, 修改 state 的 count 成 520
步骤:
- 提供mutations方法
- 提供action 方法
- 页面中 dispatch 调用
2. 辅助函数 -mapActions
actions也有辅助函数,可以将action导入到组件中
import { mapActions } from 'vuex'
methods: {
...mapActions(['setAsyncCount'])
}
/*
等价于:
methods: {
setAsyncCount (n) {
this.$store.dispatch('setAsyncCount', n)
},
}
*/
<button @click="setAsyncCount(200)">+异步</button>
4.getters(状态处理)
除了state之外,有时我们还需要从state中派生出一些状态,这些状态是依赖state的,此时会用到getters
例如,state中定义了list,为1-10的数组
在组件中我们需要显示所有大于5的数据,getters可以帮助我们实现它
步骤:
- 定义 getters
- 访问getters
① 通过 store 访问 getters
② 通过辅助函数 mapGetters 映射
5.Modules(模块化)
由于vuex使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。因此,又有了Vuex的模块化
1. 模块定义 - 准备 state
定义两个模块 user 和 setting
user中管理用户的信息状态 userInfo
const state = {
userInfo: {
name: 'zs',
age: 18
}
}
const mutations = {}
const actions = {}
const getters = {}
export default {
state,
mutations,
actions,
getters
}
setting中管理项目应用的 主题色 theme,描述 desc
const state = {
theme: 'dark'
desc: '描述真呀真不错'
}
const mutations = {}
const actions = {}
const getters = {}
export default {
state,
mutations,
actions,
getters
}
// 实例化一个仓库
const store = new Vuex.Store({
modules:{
setting,
user
}
})
使用模块中的数据, 可以直接通过模块名访问 $store.state.模块名.xxx
=> $store.state.setting.desc,
也可以通过 mapState 映射
2. 命名空间 namespaced
默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的
这句话的意思是 刚才的 user模块 还是 setting模块,它的 action、mutation 和 getter 其实并没有区分,都可以直接通过全局的方式调用, 如下图所示:
但是,如果我们想保证内部模块的高封闭性,我们可以采用namespaced来进行设置
const state = {
userInfo: {
name: 'zs',
age: 18
}
}
const mutations = {}
const actions = {}
const getters = {}
export default {
namespaced: true,
state,
mutations,
actions,
getters
}
const state = {
theme: 'dark'
desc: '描述真呀真不错'
}
const mutations = {}
const actions = {}
const getters = {}
export default {
namespaced: true,
state,
mutations,
actions,
getters
}
// 实例化一个仓库
const store = new Vuex.Store({
modules:{
setting,
user
}
})
全局的: this.$store.commit('mutation函数名', 参数)
模块中的: this.$store.commit('模块名/mutation函数名', 参数)
使用 namespaced: true 后, 要添加映射, 可以加上模块名, 找对应模块的 state/mutations/actions/getters
computed: {
// 全局的
...mapState(['count']),
// 模块中的
...mapState('user', ['myMsg']),
},
methods: {
// 全局的
...mapMutations(['addCount'])
// 模块中的
...mapMutations('user', ['updateMsg'])
}