美文网首页
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 进阶

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

  • vuex进阶

    拆封vue 我们上一次讲到讲vuex全部都写到main里面,就算最后的模块化实现也会使main看起来臃肿,不利于我...

  • 【Vuex】进阶

    1.目录结构 1.1 遵循的原则 (1) 应用层级的状态应该集中到单个 store 对象中。(2)提交 mutat...

  • 2018-03-13

    Vuex 进阶——模块化组织 Vuex 前两篇讲解了一下 Vuex 的基本使用方法,可是在实际项目中那么写肯定是不...

  • Redux 入门

    系列文章:Redux 入门(本文)Redux 进阶番外篇: Vuex — The core of Vue appl...

  • Redux 进阶

    系列文章:Redux 入门Redux 进阶(本文)番外篇: Vuex — The core of Vue appl...

  • Vue学习笔记进阶篇——vuex安装及使用

    本文为转载,原文:Vue学习笔记进阶篇——vuex安装及使用 简介 Vuex是一个专为 Vue.js 应用程序开发...

  • Vue学习笔记进阶篇——vuex核心概念

    本文为转载,原文:Vue学习笔记进阶篇——vuex核心概念 前言 本文将继续上一篇 vuex文章 ,来详细解读一下...

  • 基于Vue2.0前端框架的初步认识(素颜版)

    最近将Vue进阶文档,vuex和vue-router都看了一遍,重新写了些对初阶知识点的认识,加了些vuex和vu...

  • 使用 node 模拟请求接口

    上一篇:Vuex 进阶——模块化组织 Vuex 使用 Vue 写项目肯定会遇到一个问题,如何模拟服务端请求数据,那...

网友评论

      本文标题:Vuex 进阶

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