微信小程序 总结

微信小程序 曹卷英

第一步:项目配置

1.编写app.json

(1).pages:配置所有页面路径(必须),所有页面都需要在此列出,如果没有列出它就会报找不到某某文件路径。

(2)window: 配置窗口,配置导航及窗口的背景颜色和文字颜色,还有导航文字是否可以下拉刷新。

(3)subPackages:分包配置

(4)tabBar: tab栏配置,配置tab栏背景色及出现位置,上边框的颜色(目前只支持黑或白),文字颜色及文字选中颜色,最核心的配置是list即tab栏的列表,官方规定最少2个,最多5个,每个列表项目可配置页面路径、文字、图标及选中时图标的地址

微信截图_20180919152326.png

二.确定目录结构

  • image   --图片
  • pages   --页面
    • index --页面文件夹 ("index"为自定义的页面名称,页面相关文件的文件名需与页面名相同) 
      • index.js-- 页面逻辑
      • index.wxml --页面结构
      • index.json  --页面配置 (可以参考 app.json里面的window窗口配置)
      • index.wxss  --页面样式
  • app.js - 小程序整体逻辑 (初始化、显示、隐藏的事件,以及存放全局数据)
  • app.json - 小程序公共配置
  • app.wxss - 小程序公共样式
  • weui    --引用weui 样式
    • weui.wxss   --weui样式

第二步:编写页面

index首页

  • index.json

配置窗口标题以及下拉刷新

微信截图_20180919191351.png

  • index.wxml

用view(视图容器)进行布局

<view class='car-container'>
  <!-- 顶部信息 -->
  <view class='car-top'>
    <view class='title'>购物车 {{userInfo}}</view>
    <view class='btn-edit'>{{cargoods.length}}件</view>
  </view>
  <!-- 购物车列表 -->
  <view class='car-list'>
    <!-- 购物车产品 -->
    <view class='car-item' wx:for='{{cargoods}}'>
      <!--列表项,总长度为按钮的宽度50px+goods-info的长度 -->
      <view class='car-prod' data-index='{{index}}' style='left:{{moveLength[index]}}px;width:{{windowWidth+30}}px;' bindtouchend='moveEnd' bindtouchstart='moveStart' bindtouchmove='moving' bindtouchcancel='moveEnd'>
        <!-- 商品信息 左边有20px的填充,所以需要减去20 -->
        <view class='goods-info {{item.isBuy?"active":""}}' data-index='{{index}}' catchtap='toggleBuy' style='width:{{windowWidth-20}}px;'>
          <view class='goods-info-inner'>
            <view class='checkbox'></view>
            <view class='goods-image'>
              <image src='{{item.pic}}'></image>
            </view>
            <view class='good-info'>
              <view class='name'>{{item.name}}</view>
              <view class='footer'>
                <view class='price'>¥{{item.price}}</view>
                <view class='numbers'>
                  <view class='number-box'>
                    <view class='controler left' data-index='{{index}}' catchtap='reduceNumber'>-</view>
                    <view class='controler middle'>{{item.numbers}}</view>
                    <view class='controler right' data-index='{{index}}' catchtap='addNumber'>+</view>
                  </view>
                </view>
              </view>
            </view>
            
          </view>
        </view>
        <view class='btn-delete' data-index='{{index}}' catchtap='removeGoods'>删除</view>
      </view>
    </view>
    <!-- 没有商品信息 -->
    <view wx:if='{{cargoods.length==0}}'>
      <navigator url='/pages/index/index' open-type='switchTab' style='padding:100rpx 20rpx;'>
        购物车空空如也,赶紧去挑选你心意的产品吧~~~~~
      </navigator>
    </view>
  </view>

  <!-- 购物车底部 -->
  <view class='car-footer-container'>
    <view class='car-footer'>
      <view class='select-all {{selectAll?"active":""}}' catchtap='checkAll'>全选</view>
      <view class='btn-buy'>
        <text style='color:red;padding:0 10px;'>合计:¥{{totalPrice}}</text>
        <button type='warn' disabled='{{totalPrice==0}}' catchtap='deleteAll'>去结算</button>
      </view>
    </view>
  </view>
</view>
  • shopcar.wxss
/* 购物车顶部信息 */

.car-top {
  background-color: #efefef;
  height: 80rpx;
  line-height: 80rpx;
  padding: 0 20rpx;
}

.car-top .btn-edit {
  float: right;
}

.car-top .title {
  float: left;
}

/* 商品列表项 */

.car-list {
  padding-bottom: 47px;
}

.car-item {
  position: relative;
  padding-left: 20px;
  overflow: hidden;
}

.car-item .car-prod {
  border-bottom: 1px solid #ddd;
  position: relative;
  left: 0;
  box-sizing: border-box;
  overflow: hidden;
}

.car-prod .btn-delete {
  float: left;
  border-radius: 0;
  font-size: 30rpx;
  box-sizing: border-box;
  width: 50px;
  background-color: #e64340;
  color: #fff;
  text-align: center;
  height: 260rpx;
  line-height: 260rpx;
}

.goods-info {
  float: left;
  box-sizing: border-box;
  background: url(https://cdn.it120.cc/images/weappshop/gou.png) no-repeat 30rpx center;
  background-size: 40rpx auto;
}

.goods-info.active {
  background-image: url(https://cdn.it120.cc/images/weappshop/gou-red.png);
}

.goods-info .goods-info-inner {
  display: flex;
  padding: 40rpx 0;
}

.goods-info-inner .checkbox {
  width: 120rpx;
}

.goods-info-inner .goods-image {
  width: 180rpx;
  height: 180rpx;
}

.goods-info-inner .goods-image image {
  width: 180rpx;
  height: 180rpx;
  display: block;
}

.goods-info-inner .good-info {
  flex: 1;
  padding: 0 20rpx;
}

.goods-info-inner .good-info .name {
  width: 380rpx;
  height: 90rpx;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 10rpx 0;
  box-sizing:border-box;
}

.goods-info-inner .good-info .price {
  float: left;
  color: #e64340;
}

.goods-info-inner .good-info .numbers {
  float: right;
}

.goods-info-inner .good-info .footer {
  height: 90rpx;
  line-height: 90rpx;
}

/* 购物车底部 */

.car-footer-container {
  background-color: #efefef;
  border-top: 1px solid #ddd;
  position: fixed;
  bottom: 0;
  width: 100%;
}

.car-footer {
  display: flex;
}

.car-footer .select-all {
  background: url(https://cdn.it120.cc/images/weappshop/gou.png) no-repeat 60rpx center;
  background-size: 40rpx auto;
  text-align: right;
  height: 46px;
  line-height: 46px;
  padding-left: 120rpx;
}
.car-footer .select-all.active{
  background-image: url(https://cdn.it120.cc/images/weappshop/gou-red.png);
}

.car-footer .btn-buy {
  flex: 1;
  text-align: right;
}

.car-footer .btn-buy button {
  display: inline-block;
  vertical-align: middle;
  border-radius: 0;
}

/*商品购买数量*/
.number-box{
  display: flex;
}
.number-box .controler{
   padding: 0px 8px;
   height: 60rpx;
   line-height:60rpx;
  background-color: #efefef; 
   border: 1px solid #ddd;
}
.number-box .controler.middle{
   background-color: #fff;
   text-align: center;
  border-left: none;
  border-right: none;
  padding: 0 10px;
}
.number-box .controler.left{
 border-top-left-radius: 3px;
 border-bottom-left-radius: 3px;
}
.number-box .controler.right{
 border-top-right-radius: 3px;
 border-bottom-right-radius: 3px;
}
  • shopcar.js 逻辑处理

使用https引入图片路径 

数据表明:bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡

// pages/shopcar/shopcar.js
Page({
  data: {
    moveLength: [0, 0, 0, 0], //移动的长度
    moveStartX: [0, 0, 0, 0], //x轴移动的起点
    windowWidth: 0, //窗体的宽度
    cargoods: [], //购物车信息
    totalPrice: 0, //总价
    selectAll: false, //是否全选
    userInfo: '', //用户信息
  },
  //移动开始
  moveStart(e) {
    var index = e.currentTarget.dataset.index;
    var key = "moveStartX[" + index + "]"
    this.setData({
      //这个地方的算法有点复杂,当前坐标pageX+当前的元素移动的位置moveLength,才能保证同步移动,要考虑元素的偏移量
      [key]: e.touches[0].pageX - this.data.moveLength[index]
    });
  },
  //移动中
  moving(e) {
    var index = e.currentTarget.dataset.index;
    var key = "moveLength[" + index + "]"
    //获取移动的距离
    var length = e.changedTouches[0].pageX - this.data.moveStartX[index];
    this.setData({
      [key]: length
    });
  },
  //移动结束
  moveEnd(e) {
    var index = e.currentTarget.dataset.index;
    var key = "moveLength[" + index + "]"
    //最终移动的长度
    var len = e.changedTouches[0].pageX - this.data.moveStartX[index]
    //向左移动超过了50px
    if (len < -50) {
      len = -50; //显示删除按钮
    } else if (len == 0 || this.data.moveLength[index] == -50) {
      //由于点击时也会触发 bindtouchstart和bindtouchend事件,此时很有可能没有移动或是moveLength初始值-50的情况
      //这种情况不做任何的操作
      return;
    } else {
      len = 0; //隐藏删除按钮
    }
    this.setData({
      [key]: len
    });

  },
  onLoad: function (options) {
    var app = getApp();
    //获取全局的数据
    var globalData = app.globalData;
    console.log(globalData.cargoods)
    var sysInfo = wx.getSystemInfoSync();
    this.setData({
      windowWidth: sysInfo.windowWidth,
      cargoods: globalData.cargoods //将全局数据,赋值本地变量,方便后面的操作
    })
    this.setData({
      totalPrice: this.totalPrice()
    })
  },
  //总价计算
  totalPrice() {
    var tempGoods = this.data.cargoods;
    var totalPrice = 0;
    totalPrice = tempGoods.reduce(function (total, current) {
      if (current.isBuy) {
        return total + current.price * current.numbers;
      } else {
        return total;
      }
    }, 0)
    return parseFloat(totalPrice.toFixed(2))
  },
  //减少数量
  reduceNumber(e) {
    var index = e.currentTarget.dataset.index //获取下标
    var goods = this.data.cargoods[index];
    if (goods.numbers == 1) {
      return;
    }
    var key = 'cargoods[' + index + '].numbers';
    this.setData({
      [key]: goods.numbers - 1, // [key] 是 es5中的计算属性命名,将变量的内容作为key      
    })
    this.setData({
      totalPrice: this.totalPrice()
    })
  },
  //增加数量
  addNumber(e) {
    var index = e.currentTarget.dataset.index //获取下标
    var goods = this.data.cargoods[index];
    var key = 'cargoods[' + index + '].numbers';
    this.setData({
      [key]: goods.numbers + 1, // [key] 是 es5中的计算属性命名,将变量的内容作为key  
    })
    this.setData({
      totalPrice: this.totalPrice()
    })

  },
  //选择或取消购买
  toggleBuy(e) {
    var index =e.currentTarget.dataset.index  //获取下标
    var goods = this.data.cargoods[index];
    var key = 'cargoods[' + index + '].isBuy';
    //只要有一个没有选中,全选取消
    if (goods.isBuy) {
      this.setData({
        selectAll: false
      })
    }
    //设置购买状态
    this.setData({
      [key]: !goods.isBuy, // [key] 是 es5中的计算属性命名,将变量的内容作为key  
    })
    
    //重新计算总价
    this.setData({
      totalPrice: this.totalPrice()
    })
  },
 
  //全选,全不选
  checkAll(e) {//全选
    var checked = !this.data.selectAll;
    this.setData({
      selectAll: checked
    })
    var goods = this.data.cargoods;
    var len = goods.length;
    for (var i = 0; i < len; i++) {
      var key = 'cargoods[' + i + '].isBuy';
      this.setData({
        [key]: checked, // [key] 是 es5中的计算属性命名,将变量的内容作为key  
      })
    }
    //重新,计算总价
    this.setData({
      totalPrice: this.totalPrice()
    })
  },
  //删除商品
  removeGoods(e) {
    var index = e.currentTarget.dataset.index  //获取下标
    var goods = this.data.cargoods;
    goods.splice(index, 1)
    this.setData({
      cargoods: goods
    })
    // 删除后重新计算总价
    this.setData({
      totalPrice: this.totalPrice()
    })
    console.log(index, goods);
  },
  //结算  ,不管选没选的清除
  deleteAll(e){
    var index = e.currentTarget.dataset.index  //获取下标
    var goods = this.data.cargoods;
    goods.splice(index)
    this.setData({
      cargoods: goods
    })
  }
})

常用的:

1.使用竖向滚动时,需要给scroll-view一个固定高度,通过 WXSS 设置 height。如果scroll-view高度设置为100%,则不能触发上拉刷新和下拉加载事件......

2.image背景图片地址必须是url或者base64/本地资源无法通过 css 获取 可以使用网络图片,或者 base64,或者使用 标签

还能输出{{restrictNumber}}个字符  
  • {{reply.author}}

    {{CommonUtil.formateDate(reply.ac_CommentDate).shortTime}}
  • 回复了{{Comments.author}} :