not ending.....
Vuex简介
Vuex是一个专为Vue.js应用程序开发的状态管理模式。
devtools extension:time-travel调试、状态快照导入导出等高级调试功能。
Vuex可解决多个组件共享状态。


当是小应用的时候可用,简单的状态管理,不用Vuex
var store = {
debug: true,
state: {
message: 'Hello!'
},
setMessageAction (newValue) {
if (this.debug) console.log('setMessageAction triggered with', newValue)
this.state.message = newValue
},
clearMessageAction () {
if (this.debug) console.log('clearMessageAction triggered')
this.state.message = ''
}
}
var vmA = new Vue({
data: {
privateState: {},
sharedState: store.state
}
})
var vmB = new Vue({
data: {
privateState: {},
sharedState: store.state
}
})
Vuex使用
var store = new Vuex.Store({
states:{},
getters:{},
mutations{},
actions{},
module{}
});
//store.commit(mutations)
//store.dispatch(actions)
State
Vuex使用单一状态数。唯一数据源。
import {mapState} from 'vuex';
export default {
computed:mapState({
count:state=>state.count,
//'count'等同于state=>state.count
countAlias: 'count',
//为了使用‘this’获取局部状态,必须使用常规函数
countPlusLocalState(state){
return state.count+this.localCount
}
})
}
//或者
computed:mapState([
//映射this.count为store.state.count
'count'
])
//或者
computed:{
//使用...将此对象混入到外部对象中
localComputed(){
...mapState({})
}
}
Getter
getters:{
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
doneTodosCount:(state,getters)=>{
return getters.doneTodos.length
},
//返回一个函数,给getter传参。在对store里的数组进行查询时非常有用
getTodoById:(state)=>(id)=>{
return state.todos.find(todo=>todo.id===id)
}
}
//使用doneTodosCount
computed:{
doneTodosCount(){
return this.$store.getters.doneTodosCount
}
}
//使用getTodoById
store.getters.getTodoById(2)//{id:2,text:'...',done:false}
mapGetters辅助函数
import {mapGetters} from 'vuex';
export default {
computed:{
...mapGetters([
'doneTodosCount',
'anotherGetter'
])
//给getter属性取别名
mapGetters({
doneCount:'doneTodosCount'
})
}
}
Mutation
更改Vuex的sotre中的状态唯一方式是提交mutation。
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
});
store.commit('increment')
mutations传参
mutations: {
increment (state, n) {
state.count += n
}
}
store.commit('increment', 10)
state,payload
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
store.commit('increment',{
amout:10
})
//或者使用对象风格的提交方式
store.commit({
type:'increment',
amount:10
})
Mutation需遵守Vue的响应规则
- 最好提前在store中初始化所需的属性
- 当需要在对象上添加新属性时,应该用
Vue.set(obj,'newProp',123)- 或用新对象替换老对象
state.obj = {...state.ovj,newProp:123}
Mutation必须是同步函数
在组件中提交Mutation
在组件中用this.$store.commit('xxx')提交mutation,
或者用mapMutations辅助函数将组件中methods映射为store.commit调用(这需要在根节点注入store)
import {mapMutations} from 'vuex';
export default {
methods:{
...mapMutations([
// 将 `this.increment()` 映射为 `this.$store.commit('increment')`
'increment',
// 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
'incrementBy'
]),
...mapMutations({
// 将 `this.add()` 映射为 `this.$store.commit('increment')`
add:'increment'
})
}
}
当在mutations中使用异步,会导致你的程序很难调试。 当调用了两个包含异步调用的mutation改变状态,无法确定什么时候回调和那个先回调。这就需要确保,mutation中都是同步的。
Action
Action类似于mutation,不同于
- Action提交的是mutation,而不是直接变更状态
- Aciton可以包含任意异步操作
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
Action接受一个与store实例具有相同方法和属性的context对象,因此可调用context.commit提交一个mutation,或者通过context.state和contex.getter来获取state和getters。
//或利用参数解构简化代码
actions:{
increment({commit}){
commit('increment')
}
}
触发Aciton
store.dispatch('increment');
//带参数方式
store.dispatch('incrementAsync',{
amount:10
})
//以对象方式
store.dispatch({
type:'incrementAsync',
amount:10
})
购物车实例
actions:{
checkout({commit,state},products){
//把当前购物车的物品备份起来
const saveCardItems = [...state.cart.added];
//发出结账请求,然后乐观地清空购物车
commit(types.CHECKOUT_REQUEST);
//购物API接收一个成功回调和一个失败回调
shop.buyProducts(
products,
() => commit(types.CHECKOUT_SUCCESS),
// 失败操作
() => commit(types.CHECKOUT_FAILURE, savedCartItems)
)
}
}
以上,通过提交mutation记录action产生的副作用(即状态变更) mapActions
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')`
})
}
}
组合Action 即异步+异步
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
//调用
store.dispatch('actionA').then(() => {
// ...
})
//或在另外一个action中也可
actions: {
// ...
actionB({dispatch,commit}){
return dispatch('actionA').then(()=>{
commmit('someOtherMutation')
})
}
}
结合async/await
//假设getData()和getOtherData()返回的是Promise
actions:{
async actionA({commit}){
commit('getData',await getData())
},
async actionB({dipatch,commit}){
await dispatch('actionA')//等待actionA完成
commit('getOtherData',await getOtherData())
}
}
一个store.dispatch在不同模块下可触发多个action函数,在这种情况下,只有当所有触发函数完成后,返回的Promise才会执行。??
Module
Vuex允许将store分割成模块module。
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 的状态
模块的局部状态 局部状态可用context.state暴露,根节点状态用context.rootState rootState
const moduleA = {
// ...
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
}
}
}
}
rootState
const moduleA = {
// ...
getters: {
sumWithRootCount (state, getters, rootState) {
return state.count + rootState.count
}
}
}
not ending 命名空间 nameSpaced:true 默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。