上一篇文章:微信小程序开发一个小型商城(五、商品详情)
当我们在商品详情界面中点击添加购物后,会跳转到购物车界面,购物车界面是一个tabbar,在跳转的时候需要加上ope-type。看下购物车的静态页面把:如下图
在这里插入图片描述
页面分析:在最上面需要获取收货地址:当存在则显示信息,不存在的时候显示一个按钮表示要用户授权。下面是类似与goodlist的一个个的小商品块,再下面就类似与goods_detail当中的加入购物车那一栏。

获取用户授权,显示地址
使用wx:if else进行判断显示哪一个(授权按钮还是信息)

<view class="revice_address_row">
  <view class="address_btn" wx:if="{{!address.userName}}">
    <button bindtap="handleChooseAddress" type="primary" plain>获取收货地址</button>
  </view>
  <!-- 当收货地址 存在 详细信息就显示 -->
  <view wx:else class="user_info_row">
    <view class="user_info">
      <view>{{address.userName}}</view>
      <view>{{address.provinceName}}{{address.cityName}}{{address.countyName}}{{address.countyName}}{{address.detailInfo}}</view>
    </view>
    <view class="user_phone">{{address.telNumber}}</view>
  </view></view>

给按钮和信息加上些许样式:

.revice_address_row {
  .address_btn {
    padding: 20rpx;
    button {
      width: 60%;
    }
  }
  .user_info_row {
    display: flex;
    padding: 20rpx;
    .user_info {
      flex: 5;
    }
    .user_phone {
      flex: 3;
      text-align: right;
    }}}

商品的购买列表
先写上一个购物车,商品列表可以从good_list里面照搬一些。以及当商品为空时,同样用wx:if else 进行判断,为空后使用一种外网图片进行替换。

<view class="cart_content">
  <view class="cart_title">购物车</view>
  <view class="cart_main">
    <!--当cart数组不为0显示 -->
    <block wx:if="{{cart.length!==0}}">
      <view class="cart_item" wx:for="{{cart}}" wx:key="goods_id">
        <!--复选框-->
        <view class="cart_chk_wrap">
          <checkbox-group bindtap="handleItemChange" data-id="{{item.goods_id}}">
            <checkbox checked="{{item.checked}}"></checkbox>
          </checkbox-group>
        </view>
        <!--商品图片-->
        <navigator class="cart_img_wrap">
          <image src="{{item.goods_small_logo}}" mode="widthFix" />
        </navigator>
        <!--商品信息-->
        <view class="cart_info_wrap">
          <view class="goods_name">
            {{item.goods_name}}
          </view>
          <view class="goods_price_wrap">
            <view class="goods_price">¥{{item.goods_price}}</view>
            <view class="cart_num_tool">
              <view class="num_edit" bindtap="handleItemNumEdit" data-id="{{item.goods_id}}" data-operation="{{-1}}">-</view>
              <view class="goods_num">{{item.num}}</view>
              <view class="num_edit" bindtap="handleItemNumEdit" data-id="{{item.goods_id}}" data-operation="{{1}}">+</view>
            </view>
          </view>
        </view>
      </view>
    </block>
    <block wx:else>
      <image src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=3559485588,3499568517&fm=15&gp=0.jpg" mode="widthFix" />
    </block>
  </view>
</view>

同理goodslist界面,加上样式,多了一个复选框。使复选框居中显示。

.cart_content {
  .cart_title {
    padding: 20rpx;
    color: var(--themeColor);
    font-size: 36rpx;
    border-top: 1px solid currentColor;
    border-bottom: 1px solid currentColor;
  }
  .cart_main {
    .cart_item {
      display: flex;
      padding: 10rpx;
      border-bottom: 1px solid #ccc;
      .cart_chk_wrap {
        flex: 1;
        display: flex;
        justify-content: center;
        align-items: center;
        checkbox-group {
          checkbox {
          }
        }
      }
      .cart_img_wrap {
        flex: 2;
        display: flex;
        justify-content: center;
        align-items: center;
        image {
          width: 80%;
        }      }
      .cart_info_wrap {
        flex: 4;
        display: flex;
        flex-direction: column;
        justify-content: space-around;
        .goods_name {
          display: -webkit-box;
          overflow: hidden;
          -webkit-box-orient: vertical;
          -webkit-line-clamp: 2;
          color: #666;
        }
        .goods_price_wrap {
          display: flex;
          justify-content: space-between;
          .goods_price {
            color: var(--themeColor);
            font-size: 34rpx;
          }
          .cart_num_tool {
            display: flex;
            .num_edit {
              width: 50rpx;
              height: 50rpx;
              display: flex;
              justify-content: center;
              align-items: center;
              border: 1rpx solid #ccc;
            }
            .goods_num {
              width: 50rpx;
              height: 50rpx;
              display: flex;
              justify-content: center;
              align-items: center;}}}}}}}

立即购买
一个单纯的view,加上颜色等:以及绝对定位

<view class="footer_tool">
  <!--全选-->
  <veiw class="all_chk_wrap">
    <checkbox-group bindchange="handleItemAllchange">
      <checkbox checked="{{allchecked}}">全选</checkbox>
    </checkbox-group>
  </veiw>
  <!--总价格-->
  <view class="total_price_wrap">
    <view class="total_price">合计
      <text class="total_price_text">¥{{totalPrice}}</text>
    </view>
    <view>包含运费</view>
  </view>
  <!--结算-->
  <view class="order_pay_wrap" bindtap="handlePay">结算({{totalNum}})</view>
</view>

样式文件

.footer_tool {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 90rpx;
  background-color: #fff;
  display: flex;
  border-top: 1px solid #ccc;
  .all_chk_wrap {
    flex: 2;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .total_price_wrap {
    flex: 4;
    padding-left: 15rpx;
    .total_price {
      .total_price_text {
        color: var(--themeColor);
        font-size: 34rpx;
        font-weight: 600;
      }
    }
  }
  .order_pay_wrap {
    flex: 3;
    background-color: var(--themeColor);
    font-size: 32rpx;
    font-weight: 600;
    color: #fff;
    display: flex;
    justify-content: center;
    align-items: center;
  }
}

js文件动态获取数据及渲染

页面整合
在这个页面当中会发现会使用到很多的内置api以及方法,将这些方法进行封装以下,提升代码的性能:在util文件夹下新建一个文件ansycWx.js文件中代码如下所示:为例不让文章显得太过长就把代码格式弄了一下,复制代码后可重新整理代码格式。

export const getSetting = () => {
  return new Promise((resolve, reject) => {
    wx.getSetting({
      success: (result) => {resolve(result);},
      fail: (err) => {reject(err);},
    });
  });
};
export const chooseAddress = () => {
  return new Promise((resolve, reject) => {
    wx.chooseAddress({
      success: (result) => {resolve(result);},
      fail: (err) => {reject(err);},
    });
  });
};
export const openSetting = () => {
  return new Promise((resolve, reject) => {
    wx.openSetting({
      success: (result) => {resolve(result);},
      fail: (err) => {reject(err);},
    });
  });
};
export const login = () => {
  return new Promise((resolve, reject) => {
    wx.login({
      timeout: 10000,
      success: (result) => {resolve(result);},
      fail: (err) => {reject(err);},
    });
  });
};
export const requestPayment = (pay) => {
  return new Promise((resolve, reject) => {
    wx.requestPayment({
      ...pay,
      success: (result) => {resolve(result)},
      fail: (err) => {reject(err)},
    });
  });
};

index.js文件
在编写之前将文件进行导入:如下代码所示:

import { request } from "../../request/index.js";
import regeneratorRuntime from "../../lib/runtime/runtime";
import { getSetting, chooseAddress, openSetting } from "../../util/ansycWx.js";

在data属性中定义变量:

address: {}, //地址信息
cart: [], //购物车数组
allchecked: false, //全部选中
totalPrice: 0, //总价
totalNum: 0, //总数量

首先就是调用获取地址的api,获取值后将值进行设为缓存,再者在wxml文件当中就可以对值进行获取,并判断:

async handleChooseAddress(e) {
    console.log("获取地址");
    try {
      //获取授权状态
      const res1 = await getSetting();
      const scopeAddress = res1.authSetting["scope.address"];
      //判断授权状态
      if (scopeAddress === false) {
        await openSetting();
      }
      //调用api
      const address = await chooseAddress();
      //把值设置到缓存当中。
      wx.setStorageSync("address", address);
    } catch (error) {
      console.log(error);
    }
  },

在这个页面当中存在数据时刻独秀要进行修改,将这些代码抽离出来,使用一个新的方法进行封装。也就是对购物车当中的数据,有商品数据、是否选中。

  setCart(cart) {
    let allchecked = true;
    //申明总价格和总数量
    let totalPrice = 0;
    let totalNum = 0;
    cart.forEach((v) => {
      if (v.checked) {
        totalPrice += v.num * v.goods_price;
        totalNum += v.num;
      } else {
        allchecked = false;
      }
    });
    //判断数组是否为空
    allchecked = cart.length != 0 ? allchecked : false;
    this.setData({
      cart,
      allchecked,
      totalPrice,
      totalNum,
    });
    wx.setStorageSync("cart", cart);
  },

商品数量的加减:在加号和减号给其绑定一个单击事件,表示数量是加一还是减一,根据按钮绑定的operation值决定,并且当数量为1时,单击减号要淡出提示:问用户是否决定删除。将修改后的值cart缓存,壶盖原数组。

  handleItemNumEdit(e) {
    const { operation, id } = e.currentTarget.dataset;
    //console.log(operation,id)
    //获取购物车数组
    let { cart } = this.data;
    //找到需要修改的索引
    const index = cart.findIndex((v) => v.goods_id === id);
    //修改数量
    if (cart[index].num === 1 && operation === -1) {
      //跳出弹窗提示
      wx.showModal({
        title: "提示",
        content: "是否要删除",
        success: (result) => {
          if (result.confirm) {
            cart.splice(index, 1); //表示删除这一条数据
            this.setCart(cart);
          } else if (result.cancel) {
            console.log("取消删除");
          }
        },
      });
    } else {
      cart[index].num += operation;
      //设置回缓存和data中
      this.setCart(cart);
    }
  },

是否选中,在checked属性中,单击一次后表示选中,再次单击后取消,就类似于原先的收藏功能。切只有被选中了的商品才会进行计算到总价格当中。

  handleItemChange(e) {
    //获取id
    const goods_id = e.currentTarget.dataset.id;
    //console.log(goods_id)
    //获取购物车数组
    let { cart } = this.data;
    let index = cart.findIndex((v) => v.goods_id === goods_id);
    //取反 加上!非。
    cart[index].checked = !cart[index].checked;
    this.setCart(cart);
  },

商品的全选,在下方单击全选按钮后,对商品的所有数据的checked值改为true:即全选。

  handleItemAllchange(e) {
    let { cart, allchecked } = this.data;
    //修改选中状态
    allchecked = !allchecked;
    //循环修改cart数组当中的选中状态
    cart.forEach((v) => (v.checked = allchecked));
    //修改后的值进行填充
    this.setCart(cart);
  },

最后商品结算:单击结算按钮后需要判断是否有收货地址,以及是否有商品进行购买:条件都满足后将进行跳转到结算界面:使用wx.navigateTo进行跳转

  //商品结算
  handlePay(e) {
    //判断收货地址
    const { address, totalNum } = this.data;
    if (address.userName === "") {
      wx.showToast({
        title: "还未选择收货地址",
        icon: "none",
        success: (result) => {},
        fail: () => {},
        complete: () => {},
      });
      return;
    }
    //判断是否有选购商品
    if (totalNum === 0) {
      wx.showToast({
        title: "还未选购商品",
        icon: "none",
        success: (result) => {},
        fail: () => {},
        complete: () => {},
      });
      return;
    }
    //执行正常购买商品的逻辑,即跳转页面
    wx.navigateTo({
      url: "/pages/pay/index",
    });
  },

在storage当中可以查看到这个缓存的对象:如下图所示:
在这里插入图片描述
以及缓存当中的cart,点开cart可以看到是否选中的属性checked:如下图:
在这里插入图片描述
与此同时在appdata里面可以看到页面的对应的属性值:如下,共有5条商品 cate数组的大小为5 是否全部选中的allchecked属性值为true 、address地址信息也存在、totalPrice总价格,totalNum总条数
在这里插入图片描述
感谢你的阅览,文章持续更新中…

下一篇文章:微信小程序开发一个小型商城(七、支付页面)

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐