老师 还是上次提过的问题,在店铺里添加到了购物车,在我的购物车中数据获取的问题,按照老师的代码进行了修改,但是问题还是有点多

老师 还是上次提过的问题,在店铺里添加到了购物车,在我的购物车中数据获取的问题,按照老师的代码进行了修改,但是问题还是有点多

1、没有显示所有店铺的购物车数据

2、全选按钮有问题

3、总计价格有问题

cartList.vue页面:

<template>

  <div class="wrapper">

    <div class="title">我的全部购物车</div>

    <div v-for="(shopItem, shopId) in cartList"

         :key="shopId">

      <div class="cart">

        <div class="cart__title">

          {{shopItem.shopName}}

        </div>

        <div class="cart__wrapper">

          <div class="product__list">

            <div v-for="item in shopItem.productList"

                 :key="item.id"

                 class="product__item">

              <div class="product__item__checked iconfont"

                   v-html="item.check ? '&#xe652;': '&#xe603;'"

                   @click="() => changeCartItemChecked(shopId, item.id)" />

              <img class="product__item__img"

                   :src="item.imgUrl" />

              <div class="product__item__detail">

                <h4 class="product__item__title">{{item.name}}</h4>

                <p class="product__item__price">

                  <span class="product__item__yen">&yen;</span>{{item.price}}

                  <!-- <span class="product__item__origin">&yen;{{item.oldPrice}}</span> -->

                </p>

              </div>

              <div class="product__number">

                <span class="product__number__minus iconfont"

                      @click="() => { changeCartItemInfo(shopId, item.id, item, -1) }">&#xe677;</span>

                <span class="product__number__value">{{item.count || 0}}</span>

                <span class="product__number__plus iconfont"

                      @click="() => { changeCartItemInfo(shopId, item.id, item, 1) }">&#xe845;</span>

              </div>

            </div>

          </div>

        </div>

      </div>

    </div>

    <div class="check">

      <div class="check__all"

           @click="() => setCartItemsChecked(shopId)">

        <span class="check__all__icon iconfont"

              v-html="calculations.allChecked ? '&#xe652;': '&#xe603;'">

        </span>

        全选

      </div>

      <div class="check__info">

        总计:<span class="check__info__price">&yen; {{calculations.price}}</span>

      </div>

      <div class="check__btn"

           v-show="calculations.total > 0">

        <!-- 跳转到提交订单页面 -->

        <router-link :to="{path: `/orderConfirmation/${shopId}`}">

          去结算

        </router-link>

      </div>

    </div>

  </div>

  <Docker :currentIndex="1" />

</template>


<script>

import Docker from '../../components/Docker'

import { useStore } from 'vuex'

import { useRoute } from 'vue-router'

import { useCommonCartEffect } from '../../effects/cartEffects'


// 获取购物车信息逻辑

const useCartEffect = (shopId) => {

  const store = useStore()

  const cartList = store.state.cartList


  // 操作购物车的功能是类似的

  const changeCartItemInfo = (shopId, productId, productInfo, num) => {

    store.commit('changeCartItemInfo', {

      shopId, productId, productInfo, num

    })

  }

  const { calculations } = useCommonCartEffect(shopId)


  const changeCartItemChecked = (shopId, productId) => {

    store.commit('changeCartItemChecked', { shopId, productId })

  }


  const setCartItemsChecked = (shopId) => {

    // 如果全选状态,点击按钮后取消全选,如果非全选状态,点击按钮后全部选中

    const allChecked = !calculations.value.allChecked

    store.commit('setCartItemsChecked', { shopId, allChecked })

  }


  return {

    cartList, calculations, changeCartItemInfo, changeCartItemChecked, setCartItemsChecked

  }

}


export default {

  name: 'CartList',

  components: { Docker },

  setup () {

    const route = useRoute()

    const shopId = route.params.id

    const {

      cartList, calculations, changeCartItemInfo, changeCartItemChecked, setCartItemsChecked

    } = useCartEffect(shopId)

    return {

      cartList, calculations, changeCartItemInfo, changeCartItemChecked, setCartItemsChecked

    }

  }

}

</script>


<style lang="scss" scoped>

@import "../../style/viriables.scss";

@import "../../style/mixins.scss";

.wrapper {

  overflow-y: auto;

  position: absolute;

  left: 0;

  top: 0;

  bottom: 0.5rem;

  right: 0;

  background: #f8f8f8;

}

.title {

  line-height: 0.44rem;

  background: $bgColor;

  font-size: 0.16rem;

  color: $content-fontcolor;

  text-align: center;

}

.cart {

  margin: 0.16rem 0.18rem 0.1rem 0.18rem;

  background: $bgColor;

  border-radius: 0.04rem 0.04rem 0 0;

  &__title {

    padding: 0.16rem;

    font-size: 0.16rem;

    color: $content-fontcolor;

  }

  &__wrapper {

    overflow-y: scroll;

    margin: 0 0.18rem;

    position: absolute;

    left: 0;

    right: 0;

    top: 1.1rem;

  }

}


.product {

  &__list {

    background: $bgColor;

    border-radius: 0 0 0.04rem 0.04rem;

  }

  &__item {

    position: relative;

    display: flex;

    padding: 0.12rem 0;

    margin: 0 0.18rem;

    border-bottom: 0.01rem solid $content-bgColor;

    &__checked {

      line-height: 0.5rem;

      margin-right: 0.2rem;

      color: $btn-bgColor;

      font-size: 0.2rem;

    }

    &__detail {

      overflow: hidden;

    }

    &__img {

      width: 0.46rem;

      height: 0.46rem;

      margin-right: 0.16rem;

    }

    &__title {

      margin: 0;

      line-height: 0.2rem;

      font-size: 0.14rem;

      color: $content-fontcolor;

      @include ellipsis;

    }

    &__price {

      margin: 0.06rem 0 0 0;

      line-height: 0.2rem;

      font-size: 0.14rem;

      color: $hightlight-fontColor;

    }

    &__yen {

      font-size: 0.12rem;

    }

    &__origin {

      margin-left: 0.06rem;

      line-height: 0.2rem;

      font-size: 0.12rem;

      color: $light-fontColor;

      text-decoration: line-through;

    }

    .product__number {

      position: absolute;

      right: 0;

      bottom: 0.26rem;

      &__minus {

        position: relative;

        top: 0.02rem;

        color: $medium-fontColor;

        margin-right: 0.05rem;

        font-size: 0.2rem;

      }

      &__plus {

        position: relative;

        top: 0.02rem;

        color: $btn-bgColor;

        margin-left: 0.05rem;

        font-size: 0.2rem;

      }

      &__value {

        font-size: 0.13rem;

      }

    }

  }

}


.check {

  width: 100%;

  position: absolute;

  bottom: 0;

  display: flex;

  height: 0.49rem;

  background-color: $bgColor;

  border-top: 0.01rem solid $content-bgColor;

  line-height: 0.49rem;

  &__all {

    width: 0.64rem;

    margin-left: 0.18rem;

    font-size: 0.12rem;

    &__icon {

      display: inline-block;

      margin-right: 0.05rem;

      vertical-align: top;

      color: $btn-bgColor;

      font-size: 0.2rem;

    }

  }

  &__info {

    flex: 1;

    color: $content-fontcolor;

    font-size: 0.12rem;

    text-align: right;

    line-height: 0.49rem;

    margin-right: 0.18rem;

    &__price {

      line-height: 0.49rem;

      color: $hightlight-fontColor;

      font-size: 0.18rem;

    }

  }

  &__btn {

    width: 0.98rem;

    background-color: #4fb0f9;

    text-align: center;

    font-size: 0.14rem;

    margin-left: 0.2rem;

    a {

      color: $bgColor;

      text-decoration: none;

    }

  }

}

</style>

===============================

store -> index.js页面

import Vuex from 'vuex'

import { post } from '../utils/request'


// 给cartList数据做持久存储

const setLocalCartList = (state) => {

  const { cartList } = state

  const cartListString = JSON.stringify(cartList)

  localStorage.cartList = cartListString

}


const getLocalCartList = () => {

  // { shopId: {shopName:'', productList:{ productId: {} }}}

  try {

    return JSON.parse(localStorage.cartList)

  } catch (e) {

    return {}

  }

}


export default Vuex.createStore({

  state: {

    cartList: getLocalCartList(),

    userId: ''

  },

  mutations: {

    saveUserId (state, payload) {

      state.userId = payload.userId

    },

    changeCartItemInfo (state, payload) {

      const { shopId, productId, productInfo } = payload

      const shopInfo = state.cartList[shopId] || {

        shopName: '', productList: {}

      }

      let product = shopInfo.productList[productId]

      if (!product) {

        productInfo.count = 0

        product = productInfo

      }

      product.count = product.count + payload.num

      if (payload.num > 0) { product.check = true }

      if (product.count < 0) { product.count = 0 }

      shopInfo.productList[productId] = product

      state.cartList[shopId] = shopInfo

      console.log('cart state:', state)

      console.log('userId:', state.userId, 'shopId:', shopId, 'goodsId:', product.id, 'goodsNum:', product.count, 'goodsName:', product.goodsName, 'img:', product.imgUrl)

      // 加入购物车

      const addCart = async () => {

        try {

          const result = await post('/cart/create', {

            shopId: shopId,

            goodsId: product.id,

            goodsNum: product.count,

            goodsName: product.goodsName,

            img: product.imgUrl

          })

          if (result?.code === 1) {

            console.log('添加购物车成功')

          } else {

            console.log('添加购物车失败')

          }

        } catch (e) {

          console.log('请求失败')

        }

      }

      addCart()

      setLocalCartList(state)

    },

    changeShopName (state, payload) {

      const { shopId, shopName } = payload

      const shopInfo = state.cartList[shopId] || {

        shopName: '', productList: {}

      }

      shopInfo.shopName = shopName

      state.cartList[shopId] = shopInfo

      setLocalCartList(state)

    },

    changeCartItemChecked (state, payload) {

      const { shopId, productId } = payload

      const product = state.cartList[shopId].productList[productId]

      product.check = !product.check

      setLocalCartList(state)

    },

    cleanCartProducts (state, payload) {

      const { shopId } = payload

      state.cartList[shopId].productList = {}

      setLocalCartList(state)

    },

    setCartItemsChecked (state, payload) {

      // 接收allChecked

      const { shopId, allChecked } = payload

      const products = state.cartList[shopId].productList

      if (products) {

        for (const key in products) {

          const product = products[key]

          // 如果allChecked值为true,将每个商品的check值设为true

          if (allChecked) {

            product.check = true

          } else {

            // 如果allChecked值为false,将每个商品的check值设为false

            product.check = false

          }

        }

      }

      setLocalCartList(state)

    },

    clearCartData (state, shopId) {

      state.cartList[shopId].productList = {}

    }

  }

})






正在回答

登陆购买课程后可参与讨论,去登陆

1回答

同学你好,同学的数据和讲师的数据有区别,所以渲染时,要注意数据名称问题。老师简单修改了cartList页面,效果应该符合同学的要求了,请查看(结构和样式都有调整):

<template>
  <div class="wrapper">
    <div class="title">我的全部购物车</div>
    <!-- 遍历全部购物车数据,并渲染;shopId就是商店id -->
    <div v-for="(shopItem, shopId) in cartList" :key="shopId">
      <div class="cart">
        <div class="cart__title">
          {{ shopItem.shopName }}
        </div>
        <div class="cart__wrapper">
          <div class="product__list">
            <!-- 遍历数据,只显示count>0的 -->
            <template v-for="item in shopItem.productList" :key="item._id">
              <div v-if="item.count >0" class="product__item">
                <div
                  class="product__item__checked iconfont"
                  v-html="item.check ? '&#xe652;' : '&#xe603;'"
                  @click="() => changeCartItemChecked(shopId, item.id)"
                />
                <img class="product__item__img" :src="item.imgUrl" />
                <div class="product__item__detail">
                  <h4 class="product__item__title">{{ item.name }}</h4>
                  <p class="product__item__price">
                    <span class="product__item__yen">&yen;</span
                    >{{ item.price }}
                    <!-- <span class="product__item__origin">&yen;{{item.oldPrice}}</span> -->
                  </p>
                </div>
                <div class="product__number">
                  <span
                    class="product__number__minus iconfont"
                    @click="
                      () => {
                        changeCartItemInfo(shopId, item.id, item, -1)
                      }
                    "
                    >&#xe677;</span
                  >
                  <span class="product__number__value">{{
                    item.count || 0
                  }}</span>
                  <span
                    class="product__number__plus iconfont"
                    @click="
                      () => {
                        changeCartItemInfo(shopId, item.id, item, 1)
                      }
                    "
                    >&#xe845;</span
                  >
                </div>
              </div>
            </template>
          </div>
        </div>
      </div>
    </div>
  </div>
  <Docker :currentIndex="1" />
</template>

<script>
import Docker from '../../components/Docker'
import { useStore } from 'vuex'

// 获取购物车信息逻辑
const useCartEffect = () => {
  // 获取全部购物车数据
  const store = useStore()
  const cartList = store.state.cartList

  // 操作购物车的功能是类似的
  const changeCartItemInfo = (shopId, productId, productInfo, num) => {
    store.commit('changeCartItemInfo', {
      shopId, productId, productInfo, num
    })
  }

  const changeCartItemChecked = (shopId, productId) => {
    store.commit('changeCartItemChecked', { shopId, productId })
  }

  const setCartItemsChecked = (shopId) => {
    store.commit('setCartItemsChecked', { shopId })
  }

  return {
    cartList, changeCartItemInfo, changeCartItemChecked, setCartItemsChecked
  }
}

export default {
  name: 'CartList',
  components: { Docker },
  setup () {
    const {
      changeCartItemInfo, changeCartItemChecked, setCartItemsChecked, cartList
    } = useCartEffect()
    return {
      cartList, changeCartItemInfo, changeCartItemChecked, setCartItemsChecked
    }
  }
}
</script>

<style lang="scss" scoped>
@import '../../style/viriables.scss';
@import '../../style/mixins.scss';
.wrapper {
  overflow-y: auto;
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0.5rem;
  right: 0;
  background: #f8f8f8;
}
.title {
  line-height: 0.44rem;
  background: $bgColor;
  font-size: 0.16rem;
  color: $content-fontcolor;
  text-align: center;
}
.cart {
  margin: 0.16rem 0.18rem 0.1rem 0.18rem;
  background: $bgColor;
  border-radius: 0.04rem 0.04rem 0 0;
  &__title {
    padding: 0.16rem;
    font-size: 0.16rem;
    color: $content-fontcolor;
  }
  &__wrapper {
    overflow-y: scroll;
    margin: 0 0.18rem;
    // 这里做了修改
    // position: absolute;
    // left: 0;
    // right: 0;
    // top: 1.1rem;
  }
}

.product {
  &__list {
    background: $bgColor;
    border-radius: 0 0 0.04rem 0.04rem;
  }
  &__item {
    position: relative;
    display: flex;
    padding: 0.12rem 0;
    margin: 0 0.18rem;
    border-bottom: 0.01rem solid $content-bgColor;
    &__checked {
      line-height: 0.5rem;
      margin-right: 0.2rem;
      color: $btn-bgColor;
      font-size: 0.2rem;
    }
    &__detail {
      overflow: hidden;
    }
    &__img {
      width: 0.46rem;
      height: 0.46rem;
      margin-right: 0.16rem;
    }
    &__title {
      margin: 0;
      line-height: 0.2rem;
      font-size: 0.14rem;
      color: $content-fontcolor;
      @include ellipsis;
    }
    &__price {
      margin: 0.06rem 0 0 0;
      line-height: 0.2rem;
      font-size: 0.14rem;
      color: $hightlight-fontColor;
    }
    &__yen {
      font-size: 0.12rem;
    }
    &__origin {
      margin-left: 0.06rem;
      line-height: 0.2rem;
      font-size: 0.12rem;
      color: $light-fontColor;
      text-decoration: line-through;
    }
    .product__number {
      position: absolute;
      right: 0;
      bottom: 0.26rem;
      &__minus {
        position: relative;
        top: 0.02rem;
        color: $medium-fontColor;
        margin-right: 0.05rem;
        font-size: 0.2rem;
      }
      &__plus {
        position: relative;
        top: 0.02rem;
        color: $btn-bgColor;
        margin-left: 0.05rem;
        font-size: 0.2rem;
      }
      &__value {
        font-size: 0.13rem;
      }
    }
  }
}

.check {
  width: 100%;
  position: absolute;
  bottom: 0;
  display: flex;
  height: 0.49rem;
  background-color: $bgColor;
  border-top: 0.01rem solid $content-bgColor;
  line-height: 0.49rem;
  &__all {
    width: 0.64rem;
    margin-left: 0.18rem;
    font-size: 0.12rem;
    &__icon {
      display: inline-block;
      margin-right: 0.05rem;
      vertical-align: top;
      color: $btn-bgColor;
      font-size: 0.2rem;
    }
  }
  &__info {
    flex: 1;
    color: $content-fontcolor;
    font-size: 0.12rem;
    text-align: right;
    line-height: 0.49rem;
    margin-right: 0.18rem;
    &__price {
      line-height: 0.49rem;
      color: $hightlight-fontColor;
      font-size: 0.18rem;
    }
  }
  &__btn {
    width: 0.98rem;
    background-color: #4fb0f9;
    text-align: center;
    font-size: 0.14rem;
    margin-left: 0.2rem;
    a {
      color: $bgColor;
      text-decoration: none;
    }
  }
}
</style>

效果:

https://img1.sycdn.imooc.com//climg/625a309509712c8705340726.jpg

https://img1.sycdn.imooc.com//climg/625a30c2092db67204960310.jpg

https://img1.sycdn.imooc.com//climg/625a30d10950359404370555.jpg

https://img1.sycdn.imooc.com//climg/625a30e409f2f38f04900529.jpg

https://img1.sycdn.imooc.com//climg/625a30fb095178d105290741.jpg

至于底部的计算,同学参考其他购物车逻辑,自己计算一下。

祝学习愉快!


  • lcy_18 提问者 #1

    老师 我在我的全部购物车下面添加了全选、总计和去结算,老师可以帮忙验证一下吗,因为金额显示那边有问题

    https://img1.sycdn.imooc.com//climg/625a356a0901ed5f04250753.jpg

    https://img1.sycdn.imooc.com//climg/625a34f609d3675911360851.jpg

    2022-04-16 11:19:23
  • 好帮手慕久久 回复 提问者 lcy_18 #2

    同学你好,之前的修改少复制了一点,vuex中cartList数据,需要调整一下:

    https://img1.sycdn.imooc.com//climg/625a36c909a0b0a309020308.jpg

    其余需求,建议同学自己先实现一下,毕竟需求是同学自己的,不能总指望别人帮你实现对不对。

    项目本身就很难做,这个项目对有经验的程序员来说,可能需要2、3个月才能完成,老师也需要一点点思考、实现,同学先参考视频中的源码,自己实现下。

    2022-04-16 11:26:00
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师