Vux购物车案例

一、综合案例 - 创建项目

本案例主要针对Vuex共享数据的练习以及父子组件数据的共享。

  1. 脚手架新建项目 (注意:勾选vuex)

    版本说明:

    vue2 vue-router3 vuex3

    vue3 vue-router4 vuex4/pinia

    vue create vue-cart-demo

  2. 将原本src内容清空,替换成教学资料的《vuex-cart-准备代码》

需求:

  1. 发请求动态渲染购物车,数据存vuex (存cart模块, 将来还会有user模块,article模块...)
  2. 数字框可以修改数据
  3. 动态计算总价和总数量

二、综合案例-构建vuex-cart模块

  1. 新建 store/modules/cart.js
jsx 复制代码
export default {
  namespaced: true,
  state () {
    return {
      list: []
    }
  },
}
  1. 挂载到 vuex 仓库上 store/index.js
jsx 复制代码
import Vuex from 'vuex'
import Vue from 'vue'

import cart from './modules/cart'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    cart
  }
})

export default store

三、综合案例-准备后端接口服务环境(了解)

  1. 安装全局工具 json-server (全局工具仅需要安装一次)

    yarn global add json-server 或 npm i json-server -g

  2. 代码根目录新建一个 db 目录

  3. 将资料 index.json 移入 db 目录

    json 复制代码
    {
    "cart": [
     {
       "id": 100001,
       "name": "低帮城市休闲户外鞋天然牛皮COOLMAX纤维",
       "price": 128,
       "count": 1,
       "thumb": "https://yanxuan-item.nosdn.127.net/3a56a913e687dc2279473e325ea770a9.jpg"
     },
     {
       "id": 100002,
       "name": "网易味央黑猪猪肘330g*1袋",
       "price": 39,
       "count": 14,
       "thumb": "https://yanxuan-item.nosdn.127.net/d0a56474a8443cf6abd5afc539aa2476.jpg"
     },
     {
       "id": 100003,
       "name": "KENROLL男女简洁多彩一片式室外拖",
       "price": 128,
       "count": 2,
       "thumb": "https://yanxuan-item.nosdn.127.net/eb1556fcc59e2fd98d9b0bc201dd4409.jpg"
     },
     {
       "id": 100004,
       "name": "云音乐定制IN系列intar民谣木吉他",
       "price": 589,
       "count": 1,
       "thumb": "https://yanxuan-item.nosdn.127.net/4d825431a3587edb63cb165166f8fc76.jpg"
       }
    ]
    }
  4. 进入 db 目录,执行命令,启动后端接口服务 (使用-

  5. -watch 参数 可以实时监听 json 文件的修改)

    json-server --watch index.json

当服务启动后,可以访问http://localhost:3000/cart获取数据

四、综合案例-请求动态渲染数据

1.目标

请求获取数据存入 vuex, 映射渲染

  1. 安装 axios
jsx 复制代码
yarn add axios
  1. 准备actions 和 mutations
jsx 复制代码
import axios from 'axios'

export default {
  namespaced: true,
  state () {
    return {
      list: []
    }
  },
  mutations: {
    updateList (state, payload) {
      state.list = payload
    }
  },
  actions: {
    async getList (ctx) {
      const res = await axios.get('http://localhost:3000/cart')
      ctx.commit('updateList', res.data)
    }
  }
}
  1. App.vue页面中调用 action, 获取数据
jsx 复制代码
import { mapState } from 'vuex'

export default {
  name: 'App',
  components: {
    CartHeader,
    CartFooter,
    CartItem
  },
  created () {
    this.$store.dispatch('cart/getList')
  },
  computed: {
    ...mapState('cart', ['list'])
  }
}
  1. 动态渲染
jsx 复制代码
<!-- 商品 Item 项组件 -->
<cart-item v-for="item in list" :key="item.id" :item="item"></cart-item>

cart-item.vue

jsx 复制代码
<template>
  <div class="goods-container">
    <!-- 左侧图片区域 -->
    <div class="left">
      <img :src="item.thumb" class="avatar" alt="">
    </div>
    <!-- 右侧商品区域 -->
    <div class="right">
      <!-- 标题 -->
      <div class="title">{{item.name}}</div>
      <div class="info">
        <!-- 单价 -->
        <span class="price">¥{{item.price}}</span>
        <div class="btns">
          <!-- 按钮区域 -->
          <button class="btn btn-light">-</button>
          <span class="count">{{item.count}}</span>
          <button class="btn btn-light">+</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'CartItem',
  props: {
    item: Object
  },
  methods: {

  }
}
</script>

五、综合案例-修改数量

  1. 注册点击事件
jsx 复制代码
<!-- 按钮区域 -->
<button class="btn btn-light" @click="onBtnClick(-1)">-</button>
<span class="count">{{item.count}}</span>
<button class="btn btn-light" @click="onBtnClick(1)">+</button>
  1. 页面中dispatch action
jsx 复制代码
onBtnClick (step) {
  const newCount = this.item.count + step
  if (newCount < 1) return

  // 发送修改数量请求
  this.$store.dispatch('cart/updateCount', {
    id: this.item.id,
    count: newCount
  })
}
  1. 提供action函数
jsx 复制代码
async updateCount (ctx, payload) {
  await axios.patch('http://localhost:3000/cart/' + payload.id, {
    count: payload.count
  })
  ctx.commit('updateCount', payload)
}
  1. 提供mutation处理函数
jsx 复制代码
mutations: {
  ...,
  updateCount (state, payload) {
    const goods = state.list.find((item) => item.id === payload.id)
    goods.count = payload.count
  }
},

六、综合案例-底部总价展示

  1. 提供getters
jsx 复制代码
getters: {
  total(state) {
    return state.list.reduce((p, c) => p + c.count, 0);
  },
  totalPrice (state) {
    return state.list.reduce((p, c) => p + c.count * c.price, 0);
  },
},
  1. 动态渲染
jsx 复制代码
<template>
  <div class="footer-container">
    <!-- 中间的合计 -->
    <div>
      <span>共 {{total}} 件商品,合计:</span>
      <span class="price">¥{{totalPrice}}</span>
    </div>
    <!-- 右侧结算按钮 -->
    <button class="btn btn-success btn-settle">结算</button>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
export default {
  name: 'CartFooter',
  computed: {
    ...mapGetters('cart', ['total', 'totalPrice'])
  }
}
</script>
相关推荐
憧憬成为原神糕手9 分钟前
c++_list
开发语言·c++
idealzouhu12 分钟前
Java 并发编程 —— AQS 抽象队列同步器
java·开发语言
爱吃油淋鸡的莫何12 分钟前
Conda新建python虚拟环境问题
开发语言·python·conda
闲人编程19 分钟前
Python实现日志采集功能
开发语言·python·fluentd·filebeat·日志采集
Sol-itude26 分钟前
关于MATLAB计算3维图的向量夹角总是不正确的问题记录
开发语言·matlab·问题解决·向量
书中自有妍如玉35 分钟前
layui时间选择器选择周 日月季度年
前端·javascript·layui
Riesenzahn36 分钟前
canvas生成图片有没有跨域问题?如果有如何解决?
前端·javascript
奔驰的小野码38 分钟前
java通过org.eclipse.milo实现OPCUA客户端进行连接和订阅
java·开发语言
f89790707039 分钟前
layui 可以使点击图片放大
前端·javascript·layui
小贵子的博客39 分钟前
ElementUI 用span-method实现循环el-table组件的合并行功能
javascript·vue.js·elementui