美文网首页
Vuex 进阶

Vuex 进阶

作者: BestFei | 来源:发表于2020-03-26 11:53 被阅读0次
    一、新建一个模块

    在代码层根目录下新建一个文件夹store
    在入口main.js引入store模块,import store from './store'

    二、修改页面

    1、email的值,通过mapState的方法获取到
    2、引入组件ProductList和ShoppingCart

    <template>
      <div id="app">
        <h1>购物车示例</h1>
        <p>账号: {{email}}</p>
        <hr>
        <h2>产品</h2>
        <ProductList/>
        <hr>
        <ShoppingCart/>
      </div>
    </template>
    
    <script>
    import { mapState } from 'vuex'
    import ProductList from './components/ProductList.vue'
    import ShoppingCart from './components/ShoppingCart.vue'
    
    export default {
      computed: mapState({
        email: state => state.userInfo.email
      }),
      components: { ProductList, ShoppingCart },
    }
    </script>
    
    三、新建组件

    1、新建组件ProductList
    在目录components下新建ProductList.vue

    <template>
      <ul>
        <li
          v-for="product in products"
          :key="product.id">
          {{ product.title }} - {{ product.price }}
          <br>
          <button
            :disabled="!product.inventory"
            @click="addProductToCart(product)">
            加入购物车
          </button>
        </li>
      </ul>
    </template>
    
    <script>
    import { mapState, mapActions } from 'vuex'
    
    export default {
      computed: mapState({
        products: state => state.products.all,
      }),
      // mapState方法等同于
      // computed: {
      //   products(){
      //     return this.$store.state.products.all
      //   }
      // },
    //第一个参数cart 是命名空间
      methods: mapActions('cart', [
        'addProductToCart'
      ]),
      // mapActions方法等同于
      // methods: {
      //   addProductToCart(product){
      //     this.$store.dispatch('cart/addProductToCart', product)
      //   }
      // },
      created () {
        this.$store.dispatch('products/getAllProducts')
      }
    }
    </script>
    

    2、新建组件ShoppingCart
    在目录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>
    
    四、store模块的入口文件

    在store文件夹下新建index.js,引入cart和products组件,并注册到modules上

    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
      },
    })
    
    五、products.js
    import shop from '../../api/shop'
    import {PRODUCTS} from '../mutation-types'
    
    // initial state
    const state = {
      all: []
    }
    
    // getters
    const getters = {}
    
    // actions
    const actions = {
      getAllProducts ({ commit }) {
        shop.getProducts(products => {
          commit(PRODUCTS.SET_PRODUCTS, products)
        })
      }
    }
    
    // mutations
    const mutations = {
      [PRODUCTS.SET_PRODUCTS] (state, products) {
        state.all = products
      },
    
      [PRODUCTS.DECREMENT_PRODUCT_INVENTORY] (state, { id }) {
        const product = state.all.find(product => product.id === id)
        product.inventory--
      }
    }
    
    export default {
      namespaced: true,
      state,
      getters,
      actions,
      mutations
    }
    
    六、模块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) {
        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 })
          } else {
            commit(CART.INCREMENT_ITEM_QUANTITY, cartItem)
          }
          // remove 1 item from stock
          commit(`products/${PRODUCTS.DECREMENT_PRODUCT_INVENTORY}`, { id: product.id }, { root: true })
        }
      }
    }
    
    // mutations
    const mutations = {
      [CART.PUSH_PRODUCT_TO_CART] (state, { id }) {
        state.items.push({
          id,
          quantity: 1
        })
      },
    
      [CART.INCREMENT_ITEM_QUANTITY] (state, { id }) {
        const cartItem = state.items.find(item => item.id === id)
        cartItem.quantity++
      },
    
      [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
    }
    
    七、api
    /**
     * Mocking client-server processing
     */
    const _products = [
      {"id": 1, "title": "华为 Mate 20", "price": 3999, "inventory": 2},
      {"id": 2, "title": "小米 9", "price": 2999, "inventory": 0},
      {"id": 3, "title": "OPPO R17", "price": 2999, "inventory": 5}
    ]
    
    export default {
      getProducts (cb) {
        setTimeout(() => cb(_products), 100)
      },
    
      buyProducts (products, cb, errorCb) {
        setTimeout(() => {
          // simulate random checkout failure.
          Math.random() > 0.5
            ? cb()
            : errorCb()
        }, 100)
      }
    }
    

    相关文章

      网友评论

          本文标题:Vuex 进阶

          本文链接:https://www.haomeiwen.com/subject/txmbchtx.html