vuex
什么情况下使用vuex
构建中大型单页面应用,如果是简单的应用一般不需要使用Vuex,使用它可能是繁琐冗余的。
创建一个简单的store
1.Vuex的状态存储是响应式的,当Vue 组件从store中读取状态的时候,store变化,对应的组件也会更新。
2.不能直接改变store中的状态,想要改变它唯一的途径就是通过 commit 提交 mutation,这样可以方便跟踪每一个状态的变化。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
接下来我们可以通过 store.state 来获取状态对象,以及通过store.commit 方法触发状态变更:
store.commit('increment')
为了在vue组件中访问store,vue提供了一个从跟组件向所有子组件,以store选项注入的机制:
new Vue({
el: '#app',
store: store,
// es6简写
store
})
特别要注意的是,推荐通过提交mutation的方式来改变状态的值,不建议直接通过store.state.count来进行改变。
1.state
state 是Vuex中的基本数据!
state 就是用来存放数据,若是对数据进行处理输出,比如数据要过滤,一般我们可以写到computed中。但是如果很多组件都使用这个过滤后的数据,这就是getter存在的意义。我门可以认为,getter是store的计算属性。
2.getters
1.基础用法:
main.js
const store = new Vuex.store({
state: {
list:[1,2,3,4,5,12,23,34]
},
getters: {
filterList:state => {
return state.list.filter(item => item > 5)
}
}
})
index.vue
<script>
export default {
name: "index.vue",
computed: {
list() {
return this.$store.getters.filteredList;
}
}
}
</script>
2.内部依赖
getter 可以依赖已经定义好的getter。比如我们需要统计过滤后的数量,就可以依赖之前定义好的过滤函数。
const store = new Vuex.Store({
state: {
list: [1, 3, 5, 7, 9, 20, 30]
},
getters: {
filteredList: state => {
return state.list.filter(item => item > 5)
},
listCount: (state, getters) => {
return getters.filteredList.length;
}
}
})
取的时候和上面一样
<template>
<div>
过滤后的列表:{{list}}
<br>
列表长度:{{listCount}}
</div>
</template>
<script>
export default {
name: "index.vue",
computed: {
list() {
return this.$store.getters.filteredList;
},
listCount() {
return this.$store.getters.listCount;
}
}
}
</script>
3.mutation (提交更改数据的方法,同步!必须是同步):
使用vuex修改 state 时,有两种方式:
- 可以直接修改this.$store.state.XXX = xxx
- this.$store.dispatch(actionType, payload)或者 this. $store.commit(commitType, payload)
const store = new Vuex.Store({
strict: true, // strict: true, 若开启严格模式只要不经过 mutation的函数,则会报错
state: {
cartNum: 0, // 购物车数量
},
mutations: {
// 加1
INCREMENT(state) {
state.cartNum++;
},
}
})
methods: {
addCarts () {
baseStore.commit('INCREMENT')
},
}
异同点:
1)共同点: 能够修改state里的变量,并且是响应式的(能触发视图更新)
2)不同点:
若将vue创建 store 的时候传入 strict: true, 开启严格模式,那么任何修改state的操作,只要不经过 mutation的函数。
vue就会 throw error : [vuex] Do not mutate vuex store state outside mutation handlers。
4.action (像一个装饰器,包裹mutations,使之可以异步)
action的功能和mutation是类似的,都是去变更store里的state,不过action和mutation有两点不同:
1.action主要处理的是异步操作,mutation必须同步执行,action既可以处理同步,也可以处理异步操作。
2.action 改变状态,最后是通过提交mutation
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
setInterval(function(){
context.commit('increment')
}, 1000)
}
}
})
注意:Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
分发actions
store.dispatch('increment')
action和mutation的区别
Muation与Action作用是相同的,官网上说Mutation 必须是同步函数,Action处理异步函数。我觉得这是因为在vue devtool调试工具状态管理中,如果Mutation是异步函数,mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用就会导致devtool中状态管理不可追踪,这个问题就会导致调试非常难。而在action中的异步函数中提交mutation是可以追踪状态的。
总的来说,使用devtool调试,异步函数在muation中状态是不可追踪的,在action中状态是可以追踪的。如果你不使用devtool两者其实就是一样的,只不过mutation函数第一个参数是state,action 函数接受一个与 store 实例具有相同方法和属性的 context 对象。
5.modules (模块化Vuex)
在Vue 中state使用的是单一的状态树结构,应该的所有的状态都放在state里面,如果项目比较复杂,那state是一个很大的对象,store对象也将变得非常大,难于管理。
module:可以让每一个模块拥有自己的state,mutation,action,getters,使得结构非常清晰,方便管理。
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
命名空间
默认情况下,模块内部的action,mutation和getter是注册在全局命名空间的—这样使得多个模块能够对同一mutation或action做出响应。
如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced:true的方式使其成为带命名空间的模块。当模块被注册后,它的所有getter,action以及mutation都会自动根据模块注册的路径调整命名。