vuex

1结构

├── index.html
├── main.js
├── api
│   └── ... # 抽取出API请求
├── components
│   ├── App.vue
│   └── ...
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块

2使用

1安装
npm install vuex --save

2新建store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0,
    total: 0
  },
  getters: {
    isEven(state) {
      return state.count % 2 === 0
    }
  },
  mutations: {
    increase(state, n) {
      state.count += n
    }
  },
   actions: {//通常是在actions内执行异步操作,同步事件可直接在mutations内执行更方便
    increase({ commit }) {
      commit('increase')
    }
  },
  modules: {
    //
  }
})

export default store

3在根实例中注册 store 选项
在main.js:

import store from 'xxx/store/index'

new Vue({
  store,
  render: h => h(App)
}).$mount('#app');

通过在根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到。

3核心概念

state

一、可以从this.$store.state.xxx拿到state数据

{{this.$store.state.count}}

... console.log(this.$store.state.count)

二、引入mapState辅助函数,可以接收一个对象或数组,写在computed里面
(1)接收数组

import { mapState } from 'vuex'

export default {
  // ...
  computed: {
      ...mapState(['count','total']) //直接使用count total
  }
}

(2)接收对象

import { mapState } from 'vuex'

export default {
  // ...
  computed: {
     ...mapState({
        count: state => state.count,
        total: state => state.total
    })
  }
}

getters---store的计算属性

一、可以从this.$store.getters.xxx拿到state数据

this.xxx = this.$store.getters.xxx

二、引入mapGetters辅助函数,可以接收一个对象或数组,写在computed里面
(1)接收数组

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
      ...mapGetters(['isEven']) //可以直接使用{{isEven}}或this.isEven
  }
}

(2)接收对象

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
    ...mapGetters({
      //把 `this. myIsEven ` 映射为 `this.$store.getters. isEven`
      myIsEven: 'isEven'
    })
  }
}

mutations---更改 Vuex 的 store 中的状态的唯一方法是提交 mutation

一:this.$store.commit()

{{count}}

.... export default { // ... methods: { add(num) { this.$store.commit('increase', num) //第一个参数是mutations中方法,第二个参数是传递给该方法的参数 }, } }

对象风格的提交方式

this.$store.commit({
  type: 'increase',
  amount: 10
})

当使用对象风格的提交方式,整个对象都作为载荷传给 mutation 函数,因此 handler 保持不变:

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

使用常量替代 Mutation 事件类型

新建store/type.js:

export const SOME_MUTATION = 'SOME_MUTATION'

在store/index.js:

import Vuex from 'vuex'
import { SOME_MUTATION } from 'xx/type.js'

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})

二、引入辅助函数mapMutations,写在methods里面

{{count}}

.... export default { // ... methods: { ...mapMutations({ /// 将 `this. add()` 映射为 `this.$store.commit('increase')` add: 'increase' }), } }

actions---提交 mutation,可以包含任意异步操作

一、this.$store.dispatch()提交一个动作

...
this.$store.dispatch('increase') //increase是actions里的一个方法,通过increase去提交mutation

通常是在action里执行异步操作

actions: {
  increaseAsync ({ commit }) {
    setTimeout(() => {
      commit('increase')
    }, 1000)
  }
}

二、引入辅助函数mapActions,写在methods里面

import { mapActions } from 'vuex'

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

modules---将store分割成模块,每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  .....
  modules: {
    a: moduleA,
    b: moduleB
  }
})

//this.$store.state.a  -> moduleA 的状态
//this.$store.state.b -> moduleB 的状态

模块的局部状态

const moduleA = {
  state: { count: 0 },
  mutations: {
    increment (state) {
      // 这里的 `state` 对象是模块的局部状态
      state.count++
    }
  },

  getters: {
    doubleCount (state) {
      return state.count * 2
    }
  }
}

对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState:

const moduleA = {
  // ...
  actions: {
    incrementIfOddOnRootSum ({ state, commit, rootState }) {
      if ((state.count + rootState.count) % 2 === 1) {
        commit('increment')
      }
    }
  }
}

对于模块内部的 getter,根节点状态会作为第三个参数暴露出来:

const moduleA = {
  // ...
  getters: {
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

命名空间---namespaced: true

默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的,可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。设置后使用辅助函数要把第一个参数设置为对应的模块名。

const store = new Vuex.Store({
  modules: {
    home: {
      namespaced: true,

      // 模块内容(module assets)
      state: { ... }, // ->this.$store.state.home.count和 ...mapState('home',['count']),
      getters: {
        isAdmin () { ... } // -> this.$store.getters['home/isAdmin']和...mapGetters({isAdmin: 'home/isAdmin' }),
      },
      actions: {
        login () { ... } // -> this.$store.dispatch('home/login')
      },
      mutations: {
        login () { ... } // -> this.$store.commit('home/login')
      },
    }
  }
})

你可能感兴趣的:(vuex)