天天看點

【vue元件】vue+element ui 實作簡單購物車

效果圖:

web端

【vue元件】vue+element ui 實作簡單購物車

手機端

【vue元件】vue+element ui 實作簡單購物車

iphon5 小屏手機上效果如下:

【vue元件】vue+element ui 實作簡單購物車

代碼:

<template>
  <div>
    <div class="cart-header">
      <div class="cart-header-contain">
        <div class="cart-title">購物車</div>
      </div>
    </div>
    <!-- 網頁端樣式  -->
    <div v-if="!isMobile" class="cart-web">
      <!-- 導航欄 
		左邊logo 右邊搜尋 
		内容 單欄購物車  -->
      <div class="cart-contain">
        <div class="cart-table-container">
          <div class="cart-filter-bar">
            <span class="switch-cart">購物車(全部{{ cartTotalCount }})</span>
            <!-- <div class="cart-sum" style="display: none">
              <span class="pay-text">已選商品</span>
              <span class="total-symbol">{{ cartTotalPrice }}</span>
              <div class="pay-btn inactive-btn">結算</div>
            </div> -->
          </div>
          <div class="cart-list-content">
            <el-table
              ref="cartTable"
              :data="cartList"
              v-loading="loading"
              size="mini"
              style="width: 95%; margin: 0 auto"
              v-on:selection-change="handleSelectionChange"
            >
              <el-table-column
                type="selection"
                align="center"
                width="50"
              ></el-table-column>
              <el-table-column label="商品圖檔" width="180">
                <template slot-scope="scope">
                  <el-image
                    :src="scope.row.image"
                    style="width: 120px; height: 120px"
                  >
                    <div slot="placeholder" class="image-slot">
                      Loading<span class="dot">...</span>
                    </div>
                    <div slot="error" class="image-slot">
                      <el-image
                        style="width: 120px; height: 120px"
                        src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"
                      ></el-image>
                    </div>
                  </el-image>
                </template>
              </el-table-column>
              <el-table-column
                label="商品名稱"
                prop="productName"
              ></el-table-column>
              <el-table-column label="單價" prop="price"></el-table-column>
              <el-table-column label="數量" width="220">
                <template slot-scope="scope">
                  <el-input-number
                    setp="1"
                    :min="1"
                    v-model="scope.row.num"
                    plain
                    v-on:change="calTotalPrice()"
                  ></el-input-number>
                </template>
              </el-table-column>
              <el-table-column label="金額">
                <template slot-scope="scope">
                  <span>{{ scope.row.num * scope.row.price }}</span>
                </template>
              </el-table-column>
              <el-table-column label="操作" fixed="right" align="center">
                <template slot-scope="scope">
                  <el-button
                    size="medium"
                    type="danger"
                    v-on:click="delGood(scope.row.id)"
                    >删除</el-button
                  >
                </template>
              </el-table-column>
            </el-table>
          </div>
          <div class="cart-filter-bar-bottom">
            <div class="bar-bottom-left">
              <span class="all-check">
                <div>
                  <el-checkbox
                    class="all-check-checkbox"
                    v-model="isAllChecked"
                    v-on:change="checkAll"
                    >全選</el-checkbox
                  >
                </div>
              </span>
              <span class="all-del" v-show="isAllChecked">
                <el-button type="danger" size="small" v-on:click="delAll"
                  >删除</el-button
                >
              </span>
            </div>
            <div class="cart-sum">
              <span class="pay-text">已選商品</span>
              <span class="total-text">合計:</span>
              <span class="total-symbol">{{ cartTotalPrice }}</span>
              <div v-if="selectionData.length > 0" class="pay-btn-active">
                結算
              </div>
              <div v-else class="pay-btn-inactive">結算</div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 移動端樣式   -->
    <div v-else class="cart-phone">
      <!-- header  
		  購物車清單  
		  購物車操作欄   -->

      <div v-if="cartList.length !== 0">
        <div class="cart-box">
          <div
            v-for="(item, index) in cartList"
            :key="index"
            class="cart-list-item"
          >
            <div class="cart-item-info">
              <div class="cart-item-left">
                <div class="left-check" v-on:click="checkCurrent(item)">
                  <div class="checkbox">
                    <div v-if="item.checked" class="selected-check"></div>
                    <div v-else></div>
                  </div>
                </div>
                <el-image :src="item.image">
                  <div slot="placeholder" class="image-slot">
                    Loading<span class="dot">...</span>
                  </div>
                  <div slot="error" class="image-slot">
                    <el-image
                      fit="contain"
                      style="height: 100px"
                      src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"
                    ></el-image>
                  </div>
                </el-image>
              </div>
              <div class="cart-item-right">
                <div class="cart-item-info-content">
                  <div class="goods-name">
                    {{ item.productName }}
                  </div>

                  <div class="numbers">
                    <div class="price">價格:{{ item.price * item.num }}</div>
                  </div>
                </div>
                <div class="cart-item-opera">
                  <el-input-number
                    setp="1"
                    :min="1"
                    v-model="item.num"
                    plain
                    v-on:change="calTotalPrice()"
                  ></el-input-number>
                </div>
              </div>
            </div>

            <div class="del-btn" v-on:click="delGood(item.id)">
              <span class="fa fa-trash-o"></span>
            </div>
          </div>
        </div>
        <!-- 全選 -->
        <div class="bottom-all">
          <div class="left">
            <div class="left-check">
              <el-checkbox
                class="all-check-checkbox"
                v-model="isAllChecked"
                v-on:change="checkAll"
                >全選</el-checkbox
              >
            </div>
            <div class="del-text" v-show="isAllChecked" v-on:click="delAll">
              删除
            </div>
          </div>
          <div class="rights">
            合計:
            <span class="total-pay-count">{{ cartTotalPrice }}</span>
          </div>
          <div v-if="selectionData.length > 0" class="settlement-active">
            結算
          </div>
          <div v-else class="settlement-inactive">結算</div>
        </div>
      </div>
      <!-- 如果購物車沒有資料 -->
      <div class="cart-no-data" v-if="cartList.length == 0">
        <div>沒有資料</div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "shopCart",
  data() {
    return {
      //選中資料
      selectionData: [],
      // 購物車清單
      cartList: [],
      // 加載
      loading: false,
      // 購物車總數
      cartTotalCount: 0,
      // 購物車總價格
      cartTotalPrice: 0.0,
      // 是否是移動端
      isMobile: false,
      // 是否全選
      isAllChecked: false,
    };
  },
  created() {
    let _this = this;
    // 初始化資料
    _this.initData();
  },
  mounted() {
    let _this = this;
    // 自适應
    _this.resizeLayout();
    window.onresize = function () {
      _this.resizeLayout();
    };
  },
  components: {},
  methods: {
    // 選擇目前商品
    checkCurrent(item) {
      let _this = this;
      // 如果商品是被勾選的
      if (item.checked) {
        // 從被選擇數組中清除
        _this.selectionData.forEach((sItem, sIndex) => {
          if (sItem.id === item.id) {
            _this.selectionData.splice(sIndex, 1);
          }
        });
        // 勾選狀态變為false
        _this.cartList.forEach((cItem, cIndex) => {
          if (cItem.id === item.id) {
            _this.cartList[cIndex]["checked"] = false;
          }
        });
      } else {
        // 如果商品是未被勾選的
        // 勾選狀态變為true
        _this.cartList.forEach((cItem, cIndex) => {
          if (cItem.id === item.id) {
            _this.cartList[cIndex]["checked"] = true;
          }
        });
        // 添加到被選擇數組中
        _this.selectionData.push(item);
      }
      // 如果被選擇數組沒有資料 則全選為false
      if (_this.selectionData.length <= 0) {
        _this.isAllChecked = false;
      }
      // 如果被選擇數組數組長度和購物車數組長度相同 則全選為true
      if (_this.selectionData.length === _this.cartList.length) {
        _this.isAllChecked = true;
      }
      // 計算商品總價和總數量
      _this.calTotalPrice();
    },
    //響應式布局
    resizeLayout() {
      // 浏覽器寬
      let width =
        document.documentElement.offsetWidth || document.body.offsetWidth;
      let height =
        document.documentElement.clientHeight || document.body.clientHeight;
      let _this = this;
      if (width > 700) {
        _this.isMobile = false;
      } else {
        _this.isMobile = true;
      }
    },

    // 初始化資料
    initData() {
      let _this = this;
      _this.getList();
    },

    // 擷取購物車清單
    getList() {
      let _this = this;
      _this.cartList = [
        {
          id: "2142423",
          image: "",
          productName: "測試商品1",
          // 單價
          price: 12,
          // 購買數量
          num: 1,
          // 如果api傳回的資料中沒有類似checked這種判斷是否選中的字段
          // 可以在擷取收據後 初始化時周遊添加一遍
          checked: false,
        },
        {
          id: "2142423424",
          image: "",
          productName: "測試商品2",
          price: 32,
          num: 2,
          checked: false,
        },
      ];
    },

    // 計算總價和總數量
    calTotalPrice() {
      let _this = this;
      _this.cartTotalPrice = 0;
      _this.cartTotalCount = 0;
      // 如果有選中項
      if (_this.selectionData.length > 0) {
        _this.selectionData.forEach((item) => {
          _this.cartTotalPrice += item.num * item.price;
          _this.cartTotalCount += item.num;
        });
      }
    },
    // 控制選擇商品
    handleSelectionChange(data) {
      let _this = this;
      _this.selectionData = data;
      // 這裡嵌套循環需要優化
      _this.cartList.forEach((good) => {
        if (_this.selectionData.length > 0) {
          // 如果在被選擇數組中存在 則checked為true
          _this.selectionData.forEach((selectedItem) => {
            if (selectedItem.id === good.id) {
              good.checked = true;
            } else {
              good.checked = false;
            }
          });
        } else {
          // 如果在被選擇數組中沒有資料則checked全設定為false
          good.checked = false;
        }
      });
      let cartTotalChecked = _this.selectionData.length;
      if (_this.cartList.length === cartTotalChecked) {
        _this.isAllChecked = true;
      } else {
        _this.isAllChecked = false;
      }
      _this.calTotalPrice();
    },
    // 	全部删除
    delAll() {
      let _this = this;
      _this
        .$confirm("确定要删除全部商品嗎?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        })
        .then(function () {
          // 這裡隻是前端删除
          _this.cartList = [];
          _this.isAllChecked = false;
          // 删除後需要重新擷取資料重新整理頁面
          //   _this.getList();
        })
        .catch((e) => {
          console.log(e);
        });
    },
    // 單個删除
    delGood(id) {
      let _this = this;
      if (!id) {
        _this.$message.error("商品有誤,請重新整理後重試");
        return;
      }
      _this
        .$confirm("确定要删除此商品嗎?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        })
        .then(function () {
          let goodIndex = 0;
          _this.cartList.forEach((item, index) => {
            if (item.id === id) {
              goodIndex = index;
            }
          });
          _this.cartList.splice(goodIndex, 1);
          //   _this.getList();
        })
        .catch((e) => {
          console.log(e);
        });
    },
    // 全選
    checkAll() {
      let _this = this;
      // 如果全選
      if (_this.isAllChecked) {
        _this.getList();
        // 将購物車清單複制給被選擇數組
        _this.selectionData = JSON.parse(JSON.stringify(_this.cartList));
        _this.cartList.forEach((cItem, cIndex) => {
          _this.cartList[cIndex]["checked"] = true;
        });
        if (_this.$refs.cartTable) {
          _this.$refs.cartTable.clearSelection();
          // el table全部選中
          _this.$refs.cartTable.toggleAllSelection();
        }
      } else {
        _this.cartList.forEach((cItem, cIndex) => {
          _this.cartList[cIndex]["checked"] = false;
        });
        _this.selectionData = [];
        if (_this.$refs.cartTable) {
          // el table清空選中
          _this.$refs.cartTable.clearSelection();
        }
      }
      _this.calTotalPrice();
    },
  },
};
</script>

<style>
/* 購物車web端 */
.cart-web {
  width: 100%;
  height: auto;
  background: #e8e2e0;
}

/* 購物車移動端 */
.cart-phone {
  width: 100%;
  height: calc(100vh - 135px);
  background: #e8e2e0;
}

/* 購物車頭部 */
.cart-header {
  width: 100%;
  height: 58px;
  padding: 11px 0;
  background-color: #fff;
  display: flex;
  justify-content: center;
}

.cart-header .cart-header-contain {
  width: 80%;
  display: flex;
  align-items: center;
}

/* 購物車标題 */
.cart-header .cart-header-contain .cart-title {
  font-size: 18px;
  font-weight: 500;
}

.cart-contain {
  width: 100%;
  height: auto;
  display: flex;
  justify-content: center;
  align-items: center;
  padding-top: 24px;
}

.cart-table-container {
  width: 80%;
  border-radius: 25px;
  padding: 10px 30px;
  background: #fff;
  min-height: calc(100vh - 130px);
  position: relative;
}

.cart-filter-bar {
  width: 100%;
  display: flex;
  justify-content: space-between;
}

.cart-filter-bar .switch-cart {
  overflow: hidden;
  color: #000;
  font-size: 18px;
  font-weight: 600;
  height: 72px;
  line-height: 72px;
}

.cart-filter-bar .cart-sum {
  font-size: 14px;
  display: flex;
  align-items: center;
}

.cart-sum .total-symbol {
  font-weight: 400;
  margin-right: 12px;
  font-size: 24px;
  color: #ff5000;
}

/* 激活狀态的支付按鈕 */
.cart-sum .pay-btn-active {
  width: 74px;
  height: 42px;
  line-height: 42px;
  color: #fff;
  background: #ff5000;
  border-radius: 21px;
  text-align: center;
  cursor: pointer;
  text-decoration: none;
  font-size: 16px;
}

/* 未激活狀态的支付按鈕 */
.cart-sum .pay-btn-inactive {
  width: 74px;
  height: 42px;
  line-height: 42px;
  color: #fff;
  background: #a3a3a3;
  border-radius: 21px;
  text-align: center;
  cursor: not-allowed;
  text-decoration: none;
  font-size: 16px;
}

.inactive-btn {
  background: #aaa !important;
  color: #fff;
  cursor: not-allowed !important;
}

.cart-list-content {
  max-height: 100vh;
  padding-bottom: 72px;
  overflow-y: auto;
}

/* 購物車底部欄 */
.cart-filter-bar-bottom {
  width: 95%;
  display: flex;
  justify-content: space-between;
  position: absolute;
  bottom: 0;
  background: #fff;
  z-index: 999;
}

.cart-filter-bar-bottom .bar-bottom-left {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* 全選 */
.cart-filter-bar-bottom .all-check {
  overflow: hidden;
  color: #000;
  height: 72px;
  line-height: 72px;
  font-size: 12px;
}

.cart-filter-bar-bottom .all-check .all-check-checkbox {
  margin-right: 10px;
}

/* 全部删除 */
.cart-filter-bar-bottom .all-del {
  margin-left: 20px;
}

.cart-filter-bar-bottom .cart-sum {
  font-size: 14px;
  display: flex;
  align-items: center;
}

.cart-sum .pay-text {
  margin: 0 12px;
}

.cart-sum .total-text {
  margin: 0 0 0 12px;
}

.cart-box {
  padding: 10px 0;
}

.cart-list-item {
  position: relative;
  border-radius: 8px;
  overflow: hidden;
  border: 0;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  margin: 20px;
  background-color: #fff;
  padding: 8px 0;
}

.cart-list-item .cart-item-info {
  display: flex;
  align-items: center;
  padding: 0 0 0 15px;
}

.cart-list-item .cart-item-left {
  width: 100px;
  display: flex;
  flex-direction: row;
  align-items: center;
}

.cart-list-item .left-check {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 8%;
}

/* 單個選擇按鈕 */
.cart-list-item .left-check .checkbox {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #fff;
  border: 1px solid #b9b9b9;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 單個選擇按鈕選中 */
.cart-list-item .left-check .checkbox .selected-check {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: red;
}

.cart-item-right {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  padding: 10px;
}

.cart-item-opera {
  display: flex;
  align-items: center;
}

/* 删除按鈕 */
.del-btn {
  position: absolute;
  right: 10px;
  bottom: 10px;
  font-size: 17px;
  color: red;
}
.cart-item-right .cart-item-info-content {
  margin-right: 20px;
  width: 70px;
}

.cart-item-right .goods-name {
  width: 100%;
  font-size: 15px;
  color: #333333;
  margin-top: 3px;
  text-align: left;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.cart-item-right .numbers {
  width: 100%;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  margin-top: 10px;
}

.cart-item-right .numbers .price {
  font-size: 14px;
  line-height: 25px;
  color: #ff0000;
}

.bottom-all {
  height: 50px;
  width: 100%;
  padding: 0 2%;
  align-items: center;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  position: fixed;
  bottom: 0;
  left: 0;
  background-color: #fdfdfd;
  z-index: 11;
  border-top: 1px solid #f8f8f8;
}

.bottom-all .left {
  float: left;
  width: 28vw;
  font-size: 14px;
  position: relative;
}

.bottom-all .left .text {
  position: absolute;
  left: 35px;
  top: 50%;
  transform: translateY(-52%);
  color: #333333;
}

.bottom-all .del-text {
  color: red;
  position: absolute;
  left: 80px;
  top: 47%;
  transform: translateY(-52%);
}

.bottom-all .left-check {
  padding-left: 8px;
  flex-shrink: 0;
  height: 50px;
  margin-right: 8px;
  align-items: center;
  position: relative;
  display: flex;
}

.bottom-all .rights {
  width: 40vw;
  line-height: 50px;
  font-size: 16px;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

.bottom-all .settlement-inactive {
  padding: 0 4px;
  border-radius: 16px;
  width: 18vw;
  height: 35px;
  line-height: 35px;
  color: #ffffff;
  font-size: 17px;
  text-align: center;
  margin-right: 20px;
  cursor: not-allowed;
  background-color: #a3a3a3;
}

.bottom-all .settlement-active {
  padding: 0 4px;
  border-radius: 16px;
  width: 18vw;
  height: 35px;
  line-height: 35px;
  color: #ffffff;
  font-size: 17px;
  text-align: center;
  margin-right: 20px;
  background-color: #ff5000;
}

/* 購物車為空的樣式 */
.cart-no-data {
  text-align: center;
}

.total-pay-count {
  font-size: 24px;
  color: #ff5000;
}

@media (max-width: 700px) {
  /* 彈窗 */
  .el-message-box {
    width: 300px !important;
  }

  /* el-input-number樣式 */
  .el-input-number {
    width: 100px !important;
    line-height: 28px !important;
  }
  .el-input-number .el-input__inner {
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
  .el-input__inner {
    height: 30px !important;
  }
  .el-input-number__decrease,
  .el-input-number__increase {
    width: 20px !important;
  }
}
</style>
           

項目代碼在下面

項目位址:https://gitee.com/joeyan3/joe-vue-demo-project.git

【vue元件】vue+element ui 實作簡單購物車

繼續閱讀