目录

准备购物车数据

添加商品到购物车

保存购物车数据

查询购物车里的商品

显示购物车页面

显示商品购买数量

购买数量加减

调整数量框大小

选中购买的商品

修改商品选中状态

无货商品禁止购买

删除购物车中的商品

显示购买的商品数量

购物车结算信息


购物车

准备购物车数据

放在store中。

src\store\modules\shopcart.js

const state = {

  // { id: 商品id, count: 购买数量,selected: false  }

  car: [],

}

const getters = {}

const actions = {}

const mutations = {}

export default {

  namespaced: true,

  state,

  getters,

  actions,

  mutations

}

src\store\index.js

import shopcart from './modules/shopcart'

modules: {

  user,

  shopcart

}

添加商品到购物车

src\store\modules\shopcart.js

const mutations = {

  addCar (state, goodsinfo) {

    var flag = false

    state.car.some(item => {

      if (item.id == goodsinfo.id) {

        item.count += parseInt(goodsinfo.count)

        flag = true

        return true

      }

    })

    if (!flag) {

      state.car.push(goodsinfo)

    }

  }

}

src\pages\goods\GoodsInfo.vue

<mt-button type="danger" size="small" @click="addShopcart">加入购物车</mt-button>

addShopcart () {

  this.$store.commit('shopcart/addCar', {

    id: this.id,

    count: this.selectedCount,

    selected: true

  })

},

再vue-devtools中查看vuex添加结果。

保存购物车数据

将购物车数据保存到localStorage。

src\store\modules\shopcart.js

function setItem(name, item) {

  localStorage.setItem(name, JSON.stringify(item))

}

function getItem(name) {

  return JSON.parse(localStorage.getItem(name) || '[]')

}

const state = {

  car: getItem('car')

}

addCar (state, goodsinfo) {

  ……(原有代码)

  setItem('car', state.car)

}

测试程序,刷新页面,观察购物车里的数据(vuex)是否可以保留。

查询购物车里的商品

src\pages\Shopcart.vue

<script>

import { mapState } from 'vuex'

export default {

  computed: {

    ...mapState('shopcart', ['car']),

  },

  created () {

    this.getGoodsList()

  },

  methods: {

    getGoodsList () {

      var idArr = []

      this.car.forEach(item => idArr.push(item.id))

      if (idArr.length <= 0) {

        return

      }

      window.console.log(idArr)

    }

  }

}

</script>

到购物车页面查看商品数据是否正常

src\pages\Shopcart.vue

getGoodsList () {

  var idArr = []

  this.car.forEach(item => idArr.push(item.id))

  if (idArr.length <= 0) {

    return

  }

  this.$indicator.open({

    text: '加载中'

  })

  var params = { ids: idArr }

  this.$http.get('shopcart', { params: params }).then(res => {

    this.$indicator.close()

    window.console.log(res.data.data)

  })

}

再次查询结果:

this.$http.get('shopcart', { params: params }).then(res => {

  this.$indicator.close()

  if (res.data.code === 1) {

    this.goodslist = res.data.data

  }

})

data () {

  return {

    goodslist: []

  }

},

显示购物车页面

src\pages\Shopcart.vue

<template>

 <div class="shopcar-container">

  <div class="goods-list">

   <div class="mui-card">

    <div class="mui-card-content" v-for="(item) in goodslist" :key="item.id">

     <div class="mui-card-content-inner flex">

      <!-- 复选框 -->

      <div class="mui-input-row mui-checkbox mui-left">

       <label>&nbsp;</label>

       <input type="checkbox">

      </div>

      <!-- 中间商品图片 -->

      <img :src="item.image">

      <!-- 右侧部分 -->

      <div class="info">

       <h1>{{ item.name }}</h1>

       <p class="flex">

        <span class="price">¥{{ item.price }}</span>

        <a href="#">删除</a>

       </p>

      </div>

     </div>

    </div>

   </div>

    </div>

  </div>

</template>

样式:

<style lang="scss" scoped>

.flex {

  display: flex;

}

.shopcar-container {

  background: #eee;

  overflow: hidden;

  .goods-list {

    .mui-card-content-inner {

      align-items: center;

      padding: 10px;

      .mui-checkbox.mui-left input[type='checkbox'] {

        left: 0px;

      }

      .mui-radio.mui-left label, .mui-checkbox.mui-left label {

        padding-left: 20px;

        padding-right: 35px;

        padding-bottom: 22px;

      }

    }

    img {

      width: 60px;

    }

    .info {

      margin-left: 10px;

      width: 100%;

      overflow: hidden;

      box-sizing: border-box;

      h1 {

        font-size: 13px;

        font-weight: bold;

        line-height: 20px;

        padding-top: 10px;

      }

      p {

        display: flex;

        flex-direction: row;

        align-items: center;

        justify-content: space-between;

        .price {

          text-align: left;

          font-size: 16px;

          font-weight: 700;

          color: red;

          flex: 1

        }

        a {

          line-height: 25px;

        }

      }

    }

  }

}

</style>

向购物车中多添加几件商品,查看页面效果:

显示商品购买数量

复用numbox组件。

src\pages\Shopcart.vue

import numbox from '../components/numbox.vue'

export default {

  ……(原有代码)

  components: {

    numbox

  }

}

<!-- 右侧部分 -->

<div class="info">

  <h1>{{ item.name }}</h1>

  <p class="flex">

    <span class="price">¥{{ item.price }}</span>

    <numbox v-if="item.num" @count="countChange" :max="item.num" :goodsid="item.id"></numbox>

    <span v-else style="margin-right:20px;">该商品暂时无货</span>

    <a href="#">删除</a>

  </p>

</div>

methods: {

  ……(原有代码)

  countChange (goodsinfo) {

    window.console.log(goodsinfo)

  }

}

页面效果:

此时显示的数量不对,需要算出来。

src\store\modules\shopcart.js

const getters = {

  // 获取商品数量

  getGoodsCount (state) {

    var goods = {}

    state.car.forEach(item => {

      goods[item.id] = item.count

    })

    return goods

  }

}

src\pages\Shopcart.vue

import { mapGetters, mapState } from 'vuex'

computed: {

  ...mapState('shopcart', ['car']),

  ...mapGetters('shopcart', ['getGoodsCount'])

},

<numbox v-if="item.num" @count="countChange" :initcount="getGoodsCount[item.id]" :max="item.num" :goodsid="item.id"></numbox>

通过添加到购物车的方式,将商品100多购买几件,观察结果。

购买数量加减

src\store\modules\shopcart.js

const mutations = {

  ……(原有代码)

  updateGoodsInfo (state, goodsinfo) {

    state.car.some(item => {

      if (item.id == goodsinfo.id) {

        item.count = parseInt(goodsinfo.count)

        return true

      }

    })

    setItem('car', state.car)

  }

}

src\pages\Shopcart.vue

countChange (goodsinfo) {

  this.$store.commit('shopcart/updateGoodsInfo', goodsinfo)

},

测试程序,按“+”或“-”按钮后,商品数量会发生变化。

然后刷新页面,观察商品数量的变化是否会保存。

调整数量框大小

numbox框显得有点大了,修改一下numbox,让它可以可以自定义大小。

在使用的时候,传过来size属性,表示大小。

src\pages\Shopcart.vue

<numbox v-if="item.num" @count="countChange" :initcount="getGoodsCount[item.id]" :max="item.num" :goodsid="item.id"  size="min"></numbox>

src\components\numbox.vue

props: ['initcount', 'max', 'goodsid', 'size'],

<template>

  <div class="mui-numbox" data-numbox-min="1" :data-numbox-max="max" :style="myStyle">

    ……(原有代码)

  </div>

</template>

data () {

  return {

    myStyle: {}

  }

},

mounted () {

  ……(原有代码)

  if (this.$props.size === 'min') {

    this.myStyle = { height: '25px', margin: '0 10px 0px 10px' }

  }

},

页面效果:

选中购买的商品

src\store\modules\shopcart.js

const getters = {

  ……(原有代码)

  // 获取商品有没有选中的状态值(selected

  getGoodsSelected (state) {

    var goods = {}

    state.car.forEach(item => {

      goods[item.id] = item.selected

    })

    return goods

  }

}

src\pages\Shopcart.vue

...mapGetters('shopcart', ['getGoodsCount', 'getGoodsSelected'])

<!-- 复选框 -->

<div class="mui-input-row mui-checkbox mui-left">

  <label>&nbsp;</label>

  <input type="checkbox" v-model="getGoodsSelected[item.id]">

</div>

这时候就全部选中了。

修改商品选中状态

<input type="checkbox" v-model="getGoodsSelected[item.id]" @change="selectedChange(item.id,getGoodsSelected[item.id])">

methods: {

  ……(原有代码)

  selectedChange (id, val) {

    this.$store.commit('shopcart/updateGoodsSelected', { id: id, selected: val })

  }

}

src\store\modules\shopcart.js

const mutations = {

  ……(原有代码)

  updateGoodsSelected (state, info) {

    state.car.some(item => {

      if (item.id == info.id) {

        item.selected = info.selected

      }

    })

    setItem('car', state.car)

  }

}

访问测试,观察取消勾选后,刷新页面,是否能保存。

无货商品禁止购买

src\pages\Shopcart.vue

<input type="checkbox" v-model="getGoodsSelected[item.id]" @change="selectedChange(item.id,getGoodsSelected[item.id])" :disabled="item.num == 0">

getGoodsList () {

  ……(原有代码)

  this.$http.get('shopcart', { params: params }).then(res => {

    this.$indicator.close()

    if (res.data.code === 1) {

      this.goodslist = res.data.data

      this.goodslist.forEach(item => {

        if (item.num == 0) {

          this.selectedChange(item.id, false)

        }

      })

    }

  })

},

测试程序,登录后台,将某个购物车里的商品的库存改为0,

然后观察页面效果:

删除购物车中的商品

src\pages\Shopcart.vue

methods: {

  ……(原有代码)

  remove (id, index) {

    this.goodslist.splice(index, 1)

    this.$store.commit('shopcart/removeCar', id)

  }

}

<div class="mui-card-content" v-for="(item, i) in goodslist" :key="item.id">

  ……(原有代码)

</div>

<a href="#" @click.prevent="remove(item.id, i)">删除</a>

src\store\modules\shopcart.js

const mutations = {

  ……(原有代码)

  removeCar (state, id) {

    state.car.some((item, i) => {

      if (item.id == id) {

        state.car.splice(i, 1)

        return true

      }

    })

    setItem('car', state.car)

  }

}

测试删除功能。

显示购买的商品数量

在底部Tab栏上显示数量。

只统计选中的商品数量。

src\store\modules\shopcart.js

const getters = {

  ……(原有代码)

  // 获取选中的商品的件数

  getSelectedCount (state) {

    var count = 0

    state.car.forEach(item => {

      if (item.selected) {

        count += item.count

      }

    })

    return count

  }

}

src\components\tabbar.vue

<span class="mui-icon mui-icon-extra mui-icon-extra-cart">

  <span class="mui-badge">{{ $store.getters['shopcart/getSelectedCount'] }}</span>

</span>

<span class="mui-tab-label">购物车</span>

测试程序,当商品数量发生变化时,底部显示的购买数量也会随之变化。

购物车结算信息

结算信息包括:选中的商品件数,以及这些商品的总价格。

总件数前面已经实现了。

下面实现总价格的计算。

先获取选中的商品。

src\store\modules\shopcart.js

const getters = {

  ……(原有代码)

  // 获取选中的商品

  getSelectedGoods (state) {

    var goods = {}

    state.car.forEach(item => {

      if (item.selected) {

        goods[item.id] = item

      }

    })

    return goods

  }

}

src\pages\Shopcart.vue

<template>

  <div class="shopcar-container">

    <div class="goods-list">

      ……(原有代码)

<!-- 商品结算区域 -->

      <div class="mui-card">

        <div class="mui-card-content">

          <div class="mui-card-content-inner balance">

            <div class="left">

              <p>总计不含运费</p>

              <p>已勾选商品 <span class="red">{{ getSelectedCount }}</span> 件,总价 <span class="red">¥{{ getSelectedAmount }}</span></p>

            </div>

            <mt-button type="primary">去结算</mt-button>

          </div>

        </div>

      </div>

    </div>

  </div>

</template>

...mapGetters('shopcart', ['getGoodsCount', 'getGoodsSelected', 'getSelectedCount', 'getSelectedGoods'])

computed: {

  ……(原有代码)

  getSelectedAmount () {

    var goods = this.getSelectedGoods

    var amount = 0

    this.goodslist.forEach(item => {

      if (goods[item.id]) {

        amount += item.price * goods[item.id].count

      }

    })

    return amount

  }

},

样式:

.shopcar-container {

  ……(原有代码)

.balance {

    display: flex;

    justify-content: space-between;

    align-items: center;

    .red {

      color: red;

      font-weight: bold;

      font-size: 16px;

    }

  }

}

由于现在的商品价格都是0,看不出效果,

先到后台改一下商品价格。

页面效果:

Logo

前往低代码交流专区

更多推荐