vue - vuex 使用进阶(一)

目录:

  • 核心概念使用方法及场景:
    • state
    • mutations
    • actions
    • getters
  • 多页面公用vuex实例
    • 在页面中调用后端接口展示数据案例

参考链接:
vuex简介
vue.js的状态管理vuex中store的使用
理解vuex,看这篇就够了


本文中不再详细介绍vuex基本概念和用法,若想详细了解请参考第一链接!

1. 核心核心概念使用方法及场景:

1.1 state

单一状态管理树,只有在这里声明我们需要的数据类型和值,才能在vue组件中获取定义的对象的状态。

1.2 mutations

mutations翻译是更改,更改store中state中的状态值的唯一方法就是提交mutations,每一个mutations都有一个字符串类型的事件类型和回调函数,执行这个回调调函的方法有三个,本质上是一个:提交mutations,即commit mutations,提交时附加一些payload数据,叫做负荷。

  • 基本用法:
mutations:{
 increment(state,payload){
   state.count = payload.number  //这里改变state中的数据
 }
}

① 在actions中commit(回调函数名,payload),具体使用情况看下面的案例.

② 在组件中methods里this.$store.commit(回调函数名,payload).

③ 在组件中使用mapMutations辅助函数将组件中的mutatios映射为this.$store.commit("回调函数名",{传入的第二个}).

1.3 actions
  • 1.3.1 actions基本用法:
    actions很多地方都和mutations用法类似,最大的不同就是actions可以是异步函数,但mutations必须是同步函数,而且actions不能直接修改state,是通过commit mutations(上一内容)来改变state.声明actions时它接受的第一个参数就是和state有相同方法和属性的context对象,第二个参数也是payload。触发actions的方法:
    ① 在actions通过context.commit(mutations中回调函数名,payload)

② 在组件中methods里分发:this.$store.dispatch("mutations中回调函数名",{payload})

③ 使用 mapActions辅助函数,将组件中的methods映射为this.$store.dispatch调用

export default{
  methods:{
    ...mapActions([
        'mutations的回调函数名'
    ])
  },
/* ----------或者-----------*/
  ...mapActions({
      页面展示用的名称 : 'mutations的回调函数名'
  })
}
  • 1.3.2 actions嵌套用法:
    actions中可以是异步函数,这就使得actions中可以嵌套另外一个actions,即this.$store.dispatch()可以处理已经被触发得的actions得到的promise,处理后的结果仍返回promise对象。
  //组合性的异步嵌套actions的操作
actions:{
  actionA({commit}){
      return new Promise((resolve,reject) =>{
          setTimeout(() => {
              commit('someMutation')  //会把得到的数据保存到someMutation位置
          } ,10000)
      })
  }
}
//在某一个页面组件中触发:
 this.$store.dispatch("actionA").then(() => {
    //... 
})
//在另外一个actions中也可以这样写,actionB处理actionA被触发得到的Promise,再提交someOtherMutations
actions:{
   //...
    actionB({diapatch,commit}){
        return dispatch('actionA').then(
            commit('someOtherMutations')  
        )
    }
}
  • 再结合async await 优化组合actions的代码
actions : {
  async actionA({commit} {
    commit('gotData',await getData())
  }),
  async actionB({dispatch,commit}){
    await dispatch('actionA')  //等待actionA执行完成后再执行
    commit('gotOtherData', await getOtherData)
  }
}
1.4 getters

getter类似于Vue.js 的computed计算属性,当我们需要从state中派生一些状态就用getter函数,getter函数的第一个参数为state,还可以接受其他参数,而且它的返回值被缓存起来,只有当getter依赖值(state中的相关状态值)发生改变才会被重新计算。

  • 基本用法:
getters:{
  doneTodos : {
      return state.todosfilter(todo => todos.count)
  }
}
  • 在页面中触发getters的两种方法:
    1. 可以通过this.$store.getters.doneTodos方法可以访问得到这些派生出来的状态值
    2. 还可以使用辅助函数:
    export default{
          computed : {
             //当同时使用多个getter函数时可以这样写
              ...mapGetters([
                   'doneTodos',
                   'anotherGetters'
              ])
          }  
    }
    
  • 如果想给一个getters(doneTodos)再取一个名字,则使用对象形式
export default{
      computed : {
          ...mapGetters({
              anotherName: 'doneTodos'
          })
      }  
}
1.5 mudules

当store太过于复杂的时候对它的一种切割,每一个module都有自己的state,mutation,action和getter

moduleA = {
  state:{},
  mutations:{},
  actions:{},
getters:{}
},
moduleB = {
  state:{},
  mutations:{},
  actions:{},
getters:{}
},
const store new Vuex.Store({
  a : moduleA,
  b : moduleB
})

store.state.a // moduleA的状态
store.state.b // moduleB的状态
1.6 mudules局部状态
    1. 模块内部mutations 和getters
      对于模块内部的mutation和getter接受的第一个参数就是模块内部局部状态对象
  moduleA = {
    // ...
    state:{count:0},
    mutation : {
        increment(state){
        // 这里的state就是模块的局部状态
            state.count ++
        }
    },
    getters : {
        doubleCount(state){
            // 这里的state就是模块的局部状态
            return state.count * 2
        }
    }
  }
    1. 模块内部actions
      对于模块内部的actions,模块内部局部状态会通过 context.state方式暴露出来
    moduleA = {
      // ...
        actions : {
          increment({state,context}){
                if(context.state.count % 2 === 1){
                    context.commit('increment')
                }
           }
        }   
    }
    1. 根节点
      对于模块内部的getters和actions根节点的暴露方式:
  moduleA = {
    // ...
    //跟节点会通过第三个参数暴露出来
    getters : {
        sumWithRootCount(state,context,rootState ){
            return state.count + rooState.count
        }
    },
  //根节点状态会通过context.rootState暴露出来
    actions : {
      incrementRootSum(state,context,rootState){
          if(context.rootState.count % 2 === 1){
              context.commit('incrementRootSum')
          }
       }
    }
  }
1.7 vuex — 计算属性 — 实现双向绑定,使用带有setter的计算属性

假设obj是计算属性返回的属于vuex store中的一个对象



export default{
  //...
  computed:{
      message : {
          get(){
              return this.$store.state.obj.message
          },
          set(value){
              this.$store.commit('updateMessage',value)
          }
      }
  }
}


store中的mutaions:

  // ...
  mutatoins : {
       undateMessage(state,message){
          state.obj.message = message
      }
  }

2. 移动端多页面公用vuex案例

2.1 情景介绍:

当前端开发调用后端接口获取数据,并在多个页面中展示数据时,任意组件之间通信,最好的方法就是使用vuex.

2.2 使用方法:使用案例 https://github.com/vuejs/vuex/tree/dev/examples
  • 入口文件 : main.js
import Vue from 'vue';
import App from './components/App.vue';
import store from './store';
import { currency } from './currency'

Vue.filter('currency',currency)

var vm =  new Vue({
  el:'#app',
  store,
render : h => h(App)
})
  • 定义vuex .store: ./store/index.js中的代码
import Vue from 'vue'
import Vuex from 'vuex'
import cart from './modules/cart'
import products from './modules/products'
import createLogger from '../../../src/plugins/logger'

Vue.use(Vuex)

export default new Vuex.store({
    modules:{
      cart,
      products
    }
})
  • 创建两个module:
  1. ./store/modules/cart.js
import shop from '../../api/shop'

//初始化state
const state = () => {
    items : [ ],
    checkoutStatus : null
}


//getters
const getters = {
  cartProducts : (state,getters,rootState) =>{
      return state.item.map({id,quantity}) => {
          const product = rootState.prosucts.all.find(product => product.id === id)
            return {
              title : products.title,
              price : products.price,
              quantity
            }  
      }
  },

    cartTotalProducts : (state,getters)=>{
        return getters.cartProducts.reduce((products,total)=>{
            return total = products.price * products.quantity
        },0)
   }
}

//mutations
const mutations = {
    pushProductToCart(state,{id}){
      state.items.push({
          id,
          quantity : 1
      })
    } ,
  incrementItemQuantity (state, { id }) {
    const cartItem = state.items.find(item => item.id === id)
    cartItem.quantity++
  },

  setCartItems (state, { items }) {
    state.items = items
  },

  setCheckoutStatus (state, status) {
    state.checkoutStatus = status
  } 
}


//actions
const actions = {
  checkout ({ commit, state }, products) {
    const savedCartItems = [...state.items]
    commit('setCheckoutStatus', null)
    // empty cart
    commit('setCartItems', { items: [] })
    shop.buyProducts(
      products,
      () => commit('setCheckoutStatus', 'successful'),
      () => {
        commit('setCheckoutStatus', 'failed')
        // rollback to the cart saved before sending the request
        commit('setCartItems', { items: savedCartItems })
      }
    )
}
  1. ./store/modules/products.js
import shop from '../../api/shop';
//initial state
const state = () => ({
    all : []
})

// mutations
const mutations = {
  setProductss(state,products){
    state.all = products
  },
  decrementProductInventory(state,{id}){
    const product = state.all.find(product => product.id = id)
    product.inventory --
  }
}

//actions
const actions = {
  getAllProducts({commit}){
    shop.getProducts(products =>{
        commit('setProducts',products)
    })
  }
}

//getters
const getters = {
  
}

export default{
   namespaced = true,
   state,
   actions,
   mutations,
   getters
}
  • 通信的组件:
  1. /component/App.vue


  1. /component/ProductList.vue


  1. /component/ShoppingCart.vue


你可能感兴趣的:(vue - vuex 使用进阶(一))