vuex实现购物车案例

    科技2022-07-21  132

    Vuex购物车案例(完整实例下载)

    搭建基本环境

    前台环境

    使用vue脚手架 , 先全局安装vuecli npm i vue-cli -g

    使用vuecli创建项目 vue create cart-example cart-example是项目名字

    此时会提示,使用vue2版本的还是vue3版本,这里选择的是vue 2.x

    后台环境

    直接使用node运行根目录下的server.js就可以。

    const express = require('express') const cors = require('cors') const app = express() app.use(cors()) const hostname = '127.0.0.1' const port = 3000 //这里假装有三个产品信息 const _products = [ { id: 1, title: 'iPad Pro', price: 500.01 }, { id: 2, title: 'H&M T-Shirt White', price: 10.99 }, { id: 3, title: 'Charli XCX - Sucker CD', price: 19.99 } ] app.use(express.json()) app.get('/products', (req, res) => { res.status(200).json(_products) }) app.post('/checkout', (req, res) => { res.status(200).json({ success: Math.random() > 0.5 }) }) app.listen(port, hostname, () => { console.log(`Server is running at http://${hostname}:${port}/`) })

    创建store仓库

    在src里面创建个store文件夹,里面存储所有共享数据。

    store里面新建个index.js,外界可以访问共享数据的入口。

    import Vue from 'vue' import Vuex from 'vuex' //导入自己的两个子模块 import products from './modules/productions' import cart from './modules/cart' Vue.use(Vuex) //自己写的一个vuex插件,用于每次vuex的数据改变,就将改变后的数据存到localStorage缓存里 const myPlugin = store => { store.subscribe((mutation, state) => { //mutation打印出来,前面的type是个字符串,形如 cart/addProducts,模块名字+方法名 if(mutation.type.startsWith('cart/')){ window.localStorage.setItem('cart-products', JSON.stringify(state.cart.cartProducts)) } }) } export default new Vuex.Store({ state: { }, mutations: { }, actions: { }, //使用自己的两个子模块 modules: { products, cart }, plugins: [myPlugin] //在store中使用这个插件 })

    store中的product模块

    import axios from 'axios' //存放所有商品 const state = { products: [] } //对state的处理 const getters = {} const mutations = { setProdyctions (state, payload) { state.products = payload } } //异步获取商品数据 const actions = { async getProductions (context) { const { data } = await axios({ methods: 'GET', url: 'http://127.0.0.1:3000/products' }) //拿到数据后,调用mutation里面的方法,将data传进去 context.commit('setProdyctions', data) } } export default { namespaced: true,//开启命名空间 state, mutations, actions, getters }

    cart模块

    //购物车中的商品 const state = { cartProducts: JSON.parse(window.localStorage.getItem('cart-products')) || [] } //有时计算总价钱时会出现小数,比如 5 * 19.99 = 99.949999999,还没解决 //计算购物车中商品的数量和总价钱 const getters = { totalCount(state) { return state.cartProducts.reduce((sum, prod) => sum + prod.count, 0) }, totalPrice(state) { return state.cartProducts.reduce((sum, prod) => sum +(prod.price * prod.count), 0) }, cartCount(state) { return state.cartProducts.reduce((sum, prod) => { if (prod.isChecked) { sum += prod.count } return sum }, 0) }, cartPrice(state) { return state.cartProducts.reduce((sum, prod) => { if (prod.isChecked) { sum += prod.totalPrice } return sum }, 0) } } const mutations = { //添加商品到购物车 addToCart(state, addprod) { const prod = state.cartProducts.find(item => addprod.id === item.id) if (prod) { prod.count++, prod.isChecked = true, prod.totalPrice = prod.count * prod.price } else { state.cartProducts.push({ ...addprod, count: 1, isChecked: true, totalPrice: addprod.price }) } }, //在购物车中删除商品 deleteFromCart(state, prodId) { const index = state.cartProducts.findIndex(item => item.id === prodId) index !== -1 && state.cartProducts.splice(index, 1) }, //全选 updateAllProductChecked(state, checked) { state.cartProducts.forEach(prod => { prod.isChecked = checked }) }, //选择单个 UpdateProductChecked(state, { checked, prodId }) { const prod = state.cartProducts.find(prod => prod.id === prodId) prod && (prod.isChecked = checked) }, //更新商品的数量 UpdateProdCount(state, { prodId, count }) { const prod = state.cartProducts.find(prod => prod.id === prodId) if (prod) { prod.count = count prod.totalPrice = count * prod.price } } } const actions = { } export default { namespaced: true, state, getters, mutations, actions }

    子模块的命名空间。

    当某个组件调用一个方法时,this.$store.dispatch('addNews')任意一个子模块拥有 addNews这个方法,就会被执行,有时我们只希望只有某一个模块执行方法,此时就需要命名空间。

    当一个模块开启命名空间后,相当于被隔离,只有调用方法时指定这个弄块命名空间的名字,它里面的方法才会被执行。比如调用时这样

    ...mapActions('products', ['getProductions']),this.$store.dispatch('模块的名字/addNews')

    prod && (prod.isChecked = checked)表示,当prod为true时,才会执行后面的语句。相当于 if

    完整项目地址

    码云地址: https://gitee.com/includemain/study_-example.git

    下载后先运行npm install 安装node_module中的插件。 首页的server.js就是后台接口文件

    Processed: 0.013, SQL: 8