• 【Vue 开发实战】生态篇 # 18:Vuex最佳实践


    说明

    【Vue 开发实战】学习笔记。

    核心概念

    • State一this.$store.state.xxx 取值——mapState 取值
    • Getter 一this.$store.getters.xxx 取值——mapGetters 取值
    • Mutation 一this.$store.commit( "xxx" )赋值——mapMutations 赋值
    • Action 一 this.$store.dispatch( "xxx" )赋值——mapActions 赋值
    • Module

    使用常量替代Mutation事件类型

    在这里插入图片描述

    Module

    • 开启命名空间 namespaced: true
    • 嵌套模块不要过深,尽量扁平化
    • 灵活应用 createNamespacedHelpers

    当使用 mapState、mapGetters、mapActions 和 mapMutations 这些函数来绑定带命名空间的模块时,写起来可能比较繁琐:

    computed: {
      ...mapState({
        a: state => state.some.nested.module.a,
        b: state => state.some.nested.module.b
      }),
      ...mapGetters([
        'some/nested/module/someGetter', // -> this['some/nested/module/someGetter']
        'some/nested/module/someOtherGetter', // -> this['some/nested/module/someOtherGetter']
      ])
    },
    methods: {
      ...mapActions([
        'some/nested/module/foo', // -> this['some/nested/module/foo']()
        'some/nested/module/bar' // -> this['some/nested/module/bar']()
      ])
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    可以通过使用 createNamespacedHelpers 创建基于某个命名空间辅助函数。它返回一个对象,对象里有新的绑定在给定命名空间值上的组件绑定辅助函数:

    import { createNamespacedHelpers } from 'vuex'
    
    const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
    
    export default {
      computed: {
        // 在 `some/nested/module` 中查找
        ...mapState({
          a: state => state.a,
          b: state => state.b
        })
      },
      methods: {
        // 在 `some/nested/module` 中查找
        ...mapActions([
          'foo',
          'bar'
        ])
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    实践:购物车例子

    完整例子请查看:https://github.com/kaimo313/vue-development-practice/tree/master/vuex-demo2

    部分代码:

    vuex-demo2\src\store\mutation-types.js

    export const CART = {
      PUSH_PRODUCT_TO_CART: 'pushProductToCart',
      INCREMENT_ITEM_QUANTITY: 'incrementItemQuantity',
      SET_CART_ITEMS: 'setCartItems',
      SET_CHECKOUT_STATUS: 'setCheckoutStatus',
    }
    
    export const PRODUCTS = {
      SET_PRODUCTS:'setProducts',
      DECREMENT_PRODUCT_INVENTORY: 'decrementProductInventory'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    vuex-demo2\src\store\index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    import cart from './modules/cart'
    import products from './modules/products'
    
    Vue.use(Vuex)
    export default new Vuex.Store({
      state: {
        userInfo: {
          email: "xxxxxx@qq.com"
        }
      },
      modules: {
        cart,
        products
      },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    vuex-demo2\src\store\modules\cart.js

    import shop from '../../api/shop'
    import { CART, PRODUCTS } from '../mutation-types'
    
    // initial state
    // shape: [{ id, quantity }]
    const state = {
      items: [],
      checkoutStatus: null
    }
    
    // getters
    const getters = {
      cartProducts: (state, getters, rootState) => {
        return state.items.map(({ id, quantity }) => {
          const product = rootState.products.all.find(product => product.id === id)
          return {
            title: product.title,
            price: product.price,
            quantity
          }
        })
      },
    
      cartTotalPrice: (state, getters) => {
        return getters.cartProducts.reduce((total, product) => {
          return total + product.price * product.quantity
        }, 0)
      }
    }
    
    // actions
    const actions = {
      checkout ({ commit, state }, products) {
        const savedCartItems = [...state.items]
        commit(CART.SET_CHECKOUT_STATUS, null)
        // empty cart
        commit(CART.SET_CART_ITEMS, { items: [] })
        shop.buyProducts(
          products,
          () => commit(CART.SET_CHECKOUT_STATUS, 'successful'),
          () => {
            commit(CART.SET_CHECKOUT_STATUS, 'failed')
            // rollback to the cart saved before sending the request
            commit(CART.SET_CART_ITEMS, { items: savedCartItems })
          }
        )
      },
    
      addProductToCart ({ state, commit }, {product, number}) {
        commit(CART.SET_CHECKOUT_STATUS, null)
        if (product.inventory > 0) {
          const cartItem = state.items.find(item => item.id === product.id)
          if (!cartItem) {
            commit(CART.PUSH_PRODUCT_TO_CART, { id: product.id, number })
          } else {
            commit(CART.INCREMENT_ITEM_QUANTITY, {cartItem, number})
          }
          // remove number item from stock
          commit(`products/${PRODUCTS.DECREMENT_PRODUCT_INVENTORY}`, { id: product.id, number }, { root: true })
        }
      }
    }
    
    // mutations
    const mutations = {
      [CART.PUSH_PRODUCT_TO_CART] (state, { id, number }) {
        state.items.push({
          id,
          quantity: number
        })
      },
    
      [CART.INCREMENT_ITEM_QUANTITY] (state, { cartItem: {id}, number }) {
        const cartItem = state.items.find(item => item.id === id)
        cartItem.quantity += number
      },
    
      [CART.SET_CART_ITEMS] (state, { items }) {
        state.items = items
      },
    
      [CART.SET_CHECKOUT_STATUS] (state, status) {
        state.checkoutStatus = status
      }
    }
    
    export default {
      namespaced: true,
      state,
      getters,
      actions,
      mutations
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93

    vuex-demo2\src\components\ShoppingCart.vue

    <template>
      <div class="cart">
        <h2>清单h2>
        <p v-show="!products.length"><i>请添加产品到购物车i>p>
        <ul>
          <li
            v-for="product in products"
            :key="product.id">
            {{ product.title }} - {{ product.price }} x {{ product.quantity }}
          li>
        ul>
        <p>合计: {{ total }}p>
        <p><button :disabled="!products.length" @click="checkout(products)">提交button>p>
        <p v-show="checkoutStatus">提交 {{ checkoutStatus }}.p>
      div>
    template>
    
    <script>
    import { mapGetters, mapState } from 'vuex'
    
    export default {
      computed: {
        ...mapState({
          checkoutStatus: state => state.cart.checkoutStatus
        }),
        ...mapGetters('cart', {
          products: 'cartProducts',
          total: 'cartTotalPrice'
        }),
        // ...mapGetters({
        //   products: 'cart/cartProducts',
        //   total: 'cart/cartTotalPrice'
        // })
      },
      // computed: {
      //   checkoutStatus(){
      //     return this.$store.state.cart.checkoutStatus
      //   },
      //   products() {
      //     return this.$store.getters['cart/cartProducts']
      //   },
      //   total() {
      //     return this.$store.getters['cart/cartTotalPrice']
      //   }
      // },
      methods: {
        checkout (products) {
          this.$store.dispatch('cart/checkout', products)
        }
      },
    }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    在这里插入图片描述

  • 相关阅读:
    QT读取Excel表格内容到Table Widget
    Docker的overlay2目录占用磁盘根目录的解决办法
    pip使用豆瓣镜像源
     LeetCode199:二叉树的右视图
    ❤ npm运行打包报错归纳
    wandb----误删除了run怎么找回
    传统供应链和现代供应链有哪些区别?
    c++中指针概念及指针变量的大小
    CSDN21天学习挑战赛之折半插入排序
    阿里测试8年经验,靠着这份理解,我才得以生存下来
  • 原文地址:https://blog.csdn.net/kaimo313/article/details/126700969