阅读 830

快算算给你女朋友买礼物要花多少钱 🐱‍🏍! (仿得物微信小程序购物功能🤷‍♀️)

前言

七夕刚刚过去,想必各位为了心爱的那个ta💕在得物上花了不少钱吧。正好最近暑假正在学习微信小程序开发,与两个志同道合的小伙伴共同开发了一个仿得物APP微信小程序。这篇文章就给大家主要分享一些JS逻辑和页面设计,以及一些心得体会遇到的bug。希望能够帮到一些小程序初学者。

dewu-1.gif

项目开发准备

项目目标

  • 整个项目是基于小程序云开发的全栈项目,使用了云数据库进行数据操作。友军😘负责了购买首页、商品详情页、搜索页、品牌分类页的编写,想了解更多的可以点击传送门。而我主要负责的是登录功能和"我的"页面编写以及购买功能的实现。

功能展示以及代码分析

登录功能实现和页面样式

页面展示

结构代码

<view class="login__hd">
  <view class="login-1-1">
    <view bindtap="return">
      <image src="https://cdn.poizon.com/node-common/YmFja0AzeDE1OTM3NTU3NDQ4NDk=.png" class="login-1-1-left"></image>
    </view>
    <view class="login-1-1-auto"></view>
    <view bindtap="more">
      <image src="https://cdn.poizon.com/node-common/aG9tZUAzeDE1OTM3NTU3MDU5MjM=.png" class="login-1-1-right"></image>
    </view>
  </view>
  <view class="login__hd_title">
    <h1>登录</h1>
  </view>
</view>
<view class="login__bd">
  <view class="login__bd_pic">
    <image class="image-1"></image>
    <image class="image-2"></image>
  </view>
  <view class="login__bd_main">
    <button class="user-btn1 " openType="getUserInfo"  bindgetuserinfo="getUserInfo" >微信登录</button>
    <button  class="user-btn3 {{isAgreed?'active1': ''}}" bindtap='showtips' >微信登录</button>
    <button class="user-btn2">手机号登录/注册</button>
  </view>
  <view class="login__bd_info">
    <view class="check_btn {{activeIndex == 1?'active2': ''}}" bindtap="agree"></view>
    <view class="check_txt">
      <h1>已阅读并同意<h2 bindtap="show_detail">用户协议、隐私政策、买家须知</h2>
      </h1>
    </view>
  </view>
</view>
复制代码

当我们在没有勾选用户协议的时候是不能微信登录的,所有我在这里使用了两个样式一样的button,其中一个用三元运算符绑定了一个新的类名{{isAgreed?'active1': ''}}并且在勾选处以同样的原理绑定了{{activeIndex == 1?'active2': ''}}在勾选标签上。用以下JS逻辑即可实现勾选协议后授权登录

JS逻辑代码

Page({
  data: {
    activeIndex: 0,
    isLogged: false,
    isAgreed: false
  },
  showtips() {
    if (!this.data.isAgreed) {
      wx.showToast({
        title: '请先勾选协议',
        icon: 'none'
      })
    }
  },
  agree() {
    if (this.data.activeIndex == 0) {
      this.setData({
        activeIndex: 1,
        isAgreed: true
      })
    } else {
      this.setData({
        activeIndex: 0,
        isAgreed: false
      })
    }
    console.log(this.data.isAgreed);
  },
  getUserInfo(e) {
    // console.log(e);
    // console.log(this.data.isAgreed);
    if (e.detail.userInfo == null) {
      wx.switchTab({
        url: '../login/login',
      })
    } else {
      this.setData({
        isLogged: true
      })
      console.log(this.data.isLogged);
      if (this.data.isLogged) {
        wx.switchTab({
          url: '../buy_page/page/buy/buy'
        })
      }
    }
  },
  show_detail() {
    wx.navigateTo({
      url: '../login_detail/login_detail',
    })
  },
})
复制代码

支付页面样式

页面展示

结构展示

<van-cell title="收货人: 刘小瞳" icon="location-o" value="187****1206" size="large" label="北京字节跳动科技有限公司" is-link />

<van-card price="{{goods.price}}" desc="L 数量x1" title="{{goods.title}}" thumb="{{goods.pic}}" />
<van-cell-group>
  <van-cell title="顺丰速运" value="¥18" />
  <van-cell value-class="cell2" title="优惠卷" value="-¥15" border="{{ false }}" is-link />
</van-cell-group>
<view class="check_txt">
  <h1>1、若卖家未在36小时内发货导致交易关闭且平台未为您匹配到新订单,您将获得28.00元现金及总计人民币170元的满减优惠券补偿。</h1>
  <h1>2、每件交易商品均由平台针对实物进行鉴别,鉴于商品价格波动性,同时每个款式每个尺码的商品出售时仅有—件等情况,故不支持退还差价。</h1>
  <h1>3、企业商家ID:B21031855774654,因商品拆封鉴别,不支持七天无理由退货。</h1>
  <h1>提交订单即表示同意买家须知<h2 bindtap="show_detail">买家须知</h2>
  </h1>
</view>
<view class="pay_foot">
  <view class="payMoney">
    <h1>实付款:¥<h2>{{newPrice}}</h2></h1>
    <!--  存ID -->
    <van-button bind:click="pay" data-id="{{goods.id}}" data-title="{{goods.title}}"data-price="{{goods.price}}"data-pic="{{goods.pic}}" class="b1" type="primary" size="small" color="#01B8B9" square="true" custom-style="width: 200rpx">提交订单</van-button>
  </view>
</view>
复制代码

支付页面中地址采用van-cell。属性中可以设置titleiconlable等信息

商品信息进行了数据绑定,上一个页面点击时会将商品id传过来

JS逻辑代码

  gotoPay(e) {
    wx.navigateTo({
      url: '/pages/buy_page/page/pay/pay?id='+this.data.id,
    })
  }
复制代码

然后支付界面连接云数据库,通过传来的id查询商品的信息并setData

  const db = wx.cloud.database()
  const dewuCollection = db.collection('dewu')
  
  data: {
    goods: [],
    newPrice: 0,
    id: ''
  },
  
  async onLoad(e) {
    console.log(e);
    let id = e.id;
    console.log(id);
    await dewuCollection
      .doc(id)
      .get()
      .then(res => {
        // console.log(res.data);
        let Homedata = res.data
        this.setData({
          goods: Homedata,
          id: id
        })
      })
  },
})
复制代码

云数据库文件可自行编写成csv或者json格式导入,云数据库格式可以去这里取

我的页面样式

页面展示

dewu-8.png

结构代码

 <view class="weui-cells weui-cells_after-title my_tools">
    <!-- 购买栏 -->
    <block wx:for="{{buy}}" wx:key="index">
        <navigator style="border-bottom: none" url="{{item.url}}">
            <view class="weui-cell weui-cell_access weui-cell_example ">
                <view class="weui-cell__hd">
                    <image class="icon-img" src="{{item.icon}}"></image>
                </view>
                <view class="weui-cell__bd">{{item.title}}<p>全部订单 2</p>
                </view>
                <view class="weui-cell__ft"></view>
            </view>
        </navigator>
    </block>
    <!-- 其他栏 -->
    <block wx:for="{{collect}}" wx:key="index">
        <navigator url="{{item.url}}">
            <view class="weui-cell weui-cell_access weui-cell_example ">
                <view class="weui-cell__hd">
                    <image class="icon-img" src="{{item.icon}}"></image>
                </view>
                <view class="weui-cell__bd">{{item.title}}</view>
                <view class="weui-cell__ft"></view>
            </view>
        </navigator>
    </block>
</view>
复制代码

购买功能实现(重头戏)

页面展示

页面的设计比较简单,用vant组件都能够实现,头部的van-tabsticky吸顶,底部的结算栏用position:fixed滞留在底部

结构代码

<van-tabs color='black' sticky active="a">
  <van-tab title="待付款" name="a">
    <view class="buy__info page1">
      <view class="buy__info_goods" wx:for="{{goods}}" wx:key="index">
        <!-- 选择 -->
        <view class='icon'>
          <icon wx:if="{{item.selected}}" type="success" color="#00BABA" size="20" bindtap="selectedCart"
            data-index="{{index}}" />
          <icon wx:else type="circle" bindtap="selectedCart" size="20" data-index="{{index}}" />
        </view>
        <!-- 商品 -->
        <van-card price="{{item.price}}" desc="数量 x {{item.value}}" title="{{item.title}}" thumb="{{item.pic}}" />
        <!-- 删除 -->
        <view class='right'>
          <image
            src='https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic175.nipic.com%2Ffile%2F20180804%2F24144945_114304501035_2.jpg&refer=http%3A%2F%2Fpic175.nipic.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1631876010&t=e1da2162c6dc0c2bd878cad1a269e24d'
            bindtap='delete' data-index="{{index}}"></image>
        </view>
        <!-- 结算 -->
        <view class="cart-bottom">
          <icon wx:if="{{CheckAll}}" class="cart-icon" type="success" color="#00BABA" size="20" bindtap="select"
            data-index="{{index}}" />
          <icon wx:else type="circle" class="cart-icon" size="20" bindtap="select" data-index="{{index}}" />
          <text class='checkAll'>全选</text>

          <view class='cart-pay'>
            <text class='cart_pay' bindtap="cleanAll" data-index="{{index}}" data-id="{{item.id}}">全部结算</text>
          </view>

          <view class='cart-sum'>
            <text class='cart_sum'>
              <text class='sum_text'>合计:</text>
              <text class='sum_color'>¥{{total}}元</text>
            </text>
          </view>
        </view>
      </view>
    </view>
  </van-tab>
  <van-tab title="待发货">
    <view class="buy__info page2">
      <p>这里还没有内容</p>
    </view>
  </van-tab>
  <van-tab title="待收货">
    <view class="buy__info page3">
      <p>这里还没有内容</p>
    </view>
  </van-tab>
  <van-tab title="全部订单">
    <view class="buy__info page4">
      <view class="buy__info_goods" wx:for="{{goods}}" wx:key="index">
        <view class="buy__info_goods_hd">交易成功</view>
        <van-card price="{{item.price}}" desc="数量 x {{item.value}}" title="{{item.title}}" thumb="{{item.pic}}" />
      </view>
    </view>
  </van-tab>
</van-tabs>
复制代码

整个购物车操作实现了商品购买数量计算,价格计算,勾选绑定以及清空记录。那么该如何在不同的界面获得这些复杂的数据呢👀?

我们都知道不同页面获取数据在小程序中无非这几种方法:

  • url带参传递数据
  • 全局变量传递数据
  • 本地缓存传递数据

而想要实现这么多功能,这里使用了wx.setStorageSync(string key, Object|string data)url传参混合使用

JS逻辑代码

提交订单按钮
  pay(e) {
    let goods = wx.getStorageSync("goods") || []
    let exist = goods.find((el) => {
      console.log(e);
      return el.id == this.data.id
    })
    // console.log(e);
    //如果购物车里面有该商品那么他的数量每次加一
    if (exist) {
      exist.value = parseInt(exist.value) + 1
    } else {
      goods.push({
        id: this.data.id,
        title: e.target.dataset.title,
        pic: e.target.dataset.pic,
        price: e.target.dataset.price,
        value: 1,
        selected: true
      })
    }
    // console.log(goods);
    //更新缓存数据
    wx.setStorageSync("goods", goods)
    wx.showLoading({
      title: '提交订单中',
    })
    setTimeout(function () {
      wx.hideLoading()
      wx.showToast({
        title: '提交成功',
        icon: 'success',
        duration: 1000
      })
    }, 1000)
    setTimeout(function () {
      wx.switchTab({
        url: '../buy/buy',
      })
    }, 1500)

  },
复制代码

点击提交订单按钮,wx.getStorageSync("goods")创建key值,并且判断在购物车中是否存在该商品,如果存在则数量+1,不存在即goods.push, 并更新缓存数据。

购物车基本业务逻辑
const db = wx.cloud.database()
const dewuCollection = db.collection('dewu')

Page({
  data: {
    goods: [],
    total: 0,
    CheckAll: false
  },

  onLoad() {
    wx.setNavigationBarTitle({
      title: '我的购买'
    })
  },

  onShow() {
    let goods = wx.getStorageSync("goods")
    this.setData({
      cartList: false,
      goods: goods
    })
    console.log(goods);
  }
 
})
复制代码

在这里我们要注意this.setData应该放在onShow()函数中,因为我们要的是每次进入此页面就加载storage中的数据,所以不放在onLoad中。

选择所有商品
  // 选择所有商品
  select(e) {
    let CheckAll = this.data.CheckAll;
    CheckAll = !CheckAll
    let goods = this.data.goods

    for (let i = 0; i < goods.length; i++) {
      goods[i].selected = CheckAll
    }

    this.setData({
      goods: goods,
      CheckAll: CheckAll
    })
    this.getTotal()
  }
复制代码
选择指定商品
  // 选择商品
  selectedCart(e) {
    var goods = this.data.goods //获取购物车列表
    var index = e.currentTarget.dataset.index; //获取当前点击事件的下标索引
    var selected = goods[index].selected; //获取购物车里面的value值

    //取反
    goods[index].selected = !selected;
    this.setData({
      goods: goods
    })
    this.getTotal();
    wx.setStorageSync("goods", goods)
  }
复制代码

我们可以用 e.currentTarget.dataset.index获取当前点击事件的下标索引,然后goods[index].selected取得购物车里面的value值

删除商品
  //删除
  delete(e) {
    let goods = this.data.goods //获取购物车列表
    let index = e.currentTarget.dataset.index //获取当前点击事件的下标索引
    goods.splice(index, 1)
    this.setData({
      goods: goods
    });
    if (goods.length) {
      this.setData({
        cartList: false
      });
    }
    this.getTotal()
    wx.setStorageSync("goods", goods)
  }
复制代码

同理获取下标后也可以选择goods.splice(index, 1)删除商品

计算总价格
//合计
  getTotal() {
    let sum = 0
    for (let i = 0; i < this.data.goods.length; i++) {
      if (this.data.goods[i].selected) {
        sum += this.data.goods[i].value * this.data.goods[i].price
      }
    }
    //更新数据
    this.setData({
      total: sum
    })
  }
复制代码

最后最重要的计算商品价格来了,以后再也不怕给女朋友买礼物超额了😘

给大家的建议

各位小码农们自己在写项目的时候有bug就多打断点多console.log()看看自己哪里出了问题,如果没有报错但是数据有没拿到,那就仔细检查一些直接调用时有没有出现拼写错误。在处理复杂业务逻辑时不妨先想清楚,再下手也不迟。设计页面的时候多看看多学学微信小程序开发文档和Vant Vant Weapp

本项目源码

需要的小伙伴可以去Gitee上取噢!

结语

经历过合作开发的程序猿应该都有着同感,项目开发应该是件高兴的事,可是问题又来了,以前只是个人开发项目啊,文档写写,图画画,自己能看懂就得了,最主要是写代码,把软件设计完成就可以万事大吉了。但通过现在合作开发,不是你个人的项目,大家共同努力才可以写出一个好的项目。非常感谢在我写项目过程中帮助过我的老师和同学。如果你喜欢我的这篇文章或者看到这里对你有些许帮助,不妨点个赞吧😺!

dewu-3.gif

文章分类
前端
文章标签