使用微信小程序自定义组件实现的tabs选项卡功能

一个自定义组件由 json wxml wxss js 4个文件组成。要编写一个自定义组件,首先需要在 json 文件中进行自定义组件声明(将 component 字段设为 true 可这一组文件设为自定义组件)


components/navigator/index.json

{
  "component": true
}

components/navigator/index.wxml

<!-- 自定义tab标签组件-->
<!-- 标题列表-->
<scroll-view scroll-x="true" class="scroll-view-x" wx:if="{{!ttype || ttype==2}}">
  <view  class="scroll-view-item" wx:for="{{tList}}" wx:key="*this">
    <view class="{{currentTab==(index) ? 'on' : ''}}" bindtap="_swichNav" data-current="{{index}}">{{ !tname ? item.name : item[tname].name }}</view>
  </view>
</scroll-view>
<!--内容列表-->
<slot>
</slot>

components/navigator/index.js

//组件的对外属性,是属性名到属性设置的映射表,属性设置中可包含三个字段, type 表示属性类型、 value 表示属性初始值、 observer 表示属性值被更改时的响应函数
Component({
  properties:{
    //标题列表
    tList:{
      type: Array,
      value:[]
    }, 
    //当前tab index
    currentTab:{
      type:Number,
      value:0,
      observer: function (newVal, oldVal) { 
        this.setData({
          currentTab : newVal
        })
      } 
    }
  },
  //组件的方法,包括事件响应函数和任意的自定义方法,关于事件响应函数的使用
  methods:{
    // 内部方法建议以下划线开头
    _swichNav:function(e){
      //自定义组件触发事件时,需要使用 triggerEvent 方法,指定事件名、detail对象和事件选项
      this.triggerEvent('changeCurrent', {
        currentNum: e.currentTarget.dataset.current
      })
    }
  }
})

components/navigator/index.wxss

.scroll-view-x{
  background-color: #fff;
  white-space: nowrap;
  position:fixed;
  z-index:10;
  top:0
}
.scroll-view-x .scroll-view-item{
  display:inline-block;
  margin:0 35rpx;
  line-height: 33px;
  cursor: pointer;
}
.on{
  border-bottom: 2px solid red;
  color: red
}

使用自定义组件

使用已注册的自定义组件前,首先要在页面的 json 文件中进行引用声明。此时需要提供每个自定义组件的标签名和对应的自定义组件文件路径:


pages/order-list/index.json

{
    "navigationBarTitleText":"订单列表",
    "usingComponents": {
      "slideTab": "../../components/navigator/index"
    }
}

这样,在页面的 wxml 中就可以像使用基础组件一样使用自定义组件。节点名即自定义组件的标签名,节点属性即传递给组件的属性值。
pages/order-list/index.wxml

<view >
    <slideTab tList="{{statusType}}"   bind:changeCurrent="swichNav" currentTab="{{currentType}}" >
      <swiper current="{{currentType}}" duration="300" bindchange="bindChange" style="height: {{windowHeight-35}}px;margin-top:35px;">
        <block>
          <swiper-item wx:for="{{list}}">
            <view class="no-order" hidden="{{item.length ? true : false}}">
              <image src="../../assets/imgs/no-order.png" class="no-order-img"></image>
              <view class="text">暂无订单</view>
            </view>
            <scroll-view scroll-y="true" class="order-list" scroll-with-animation="true" lower-threshold="1" bindscrolltolower="scrolltolower" style="height: {{windowHeight-35}}px;" hidden="{{item ? flase : true}}">
              <view class="a-order" wx:for="{{item}}"  wx:key="childIndex" wx:for-item="childItem" >
                <view class="order-date">
                    <view class="date-box">下单时间:{{childItem.dateAdd}}</view>
                    <view class="status {{(childItem.status==-1 || childItem.status==4) ? '':'red'}}">{{item.statusStr}}</view>
                </view>
                <view class="goods-info" bindtap="orderDetail" data-id="{{childItem.id}}">
                    <view class="goods-des">
                      <view>订单号 : {{childItem.orderNumber}} </view>
                      <view wx:if="{{childItem.remark && childItem.remark != ''}}">备注: {{item.remark}}</view>
                    </view>
                </view>
                <view >
                    <scroll-view class="goods-img-container" scroll-x="true">
                        <view class="img-box" wx:for="{{goodsMap[currentType][childItem.id]}}" wx:for-item="child_item">
                            <image src="{{child_item.pic}}" class="goods-img"></image>
                        </view>
                    </scroll-view>
                </view>
                <view class="price-box">
                    <view class="total-price">合计:¥ {{childItem.amountReal}}</view>
                    <view class="btn cancel-btn" hidden="{{childItem.status==0? false : true}}" bindtap="cancelOrderTap"  data-id="{{childItem.id}}">取消订单</view>
                    <view class="btn topay-btn" hidden="{{childItem.status==0? fslse : true}}" bindtap="toPayTap" data-id="{{childItem.id}}" data-money="{{childItem.amountReal}}">马上付款</view>        
                </view>  
              </view>
            </scroll-view>
          </swiper-item>
        </block>
      </swiper>
    </slideTab>
</view>

pages/order-list/index.js

var wxpay = require('../../utils/pay.js')
var app = getApp();
Page({
  data:{
    statusType:[
      {name:"待付款",page:0},
      {name:"待发货",page:0},
      {name:"待收货",page:0},
      {name:"待评价",page:0},
      {name:"已完成",page:0}],
    currentType:0,
    list:[[],[],[],[],[]],
    goodsMap:[{},{},{},{},{}],
    logisticsMap:[{},{},{},{},{}],
    windowHeight:''
  },
  onLoad(options){
    this.getList();
    var systemInfo = wx.getSystemInfoSync()
    this.setData({
      windowHeight: systemInfo.windowHeight,
      currentType:options.id ? options.id:0
    })
  },
  // 点击tab切换 
  swichNav: function (res) {
    if (this.data.currentType == res.detail.currentNum) return;
    this.setData({
      currentType: res.detail.currentNum
    })
  } , 
  bindChange:function(e){
    this.setData({
      currentType: e.detail.current
    })
    if (!this.data.list[e.detail.current].length)
      this.getList();
  } ,
  getList(){
    wx.showLoading();
    var that = this;
    var postData = {
      token: app.globalData.token,
      status: that.data.currentType
    };
    var _page = that.data.statusType[that.data.currentType].page+1 ;;
    wx.request({
      url: app.globalData.baseUrl + '/order/list',
      data: postData,
      success: (res) => {
        wx.hideLoading();
        var param = {}, str1 = "list[" + that.data.currentType + "]", str2 = 'statusType[' + that.data.currentType + '].page', str3 = "logisticsMap[" + that.data.currentType + "]", str4 = "goodsMap[" + that.data.currentType + "]" ;
        if (res.data.code == 0) {
          param[str1] = res.data.data.orderList ;
          param[str2] = _page ;
          param[str3] = res.data.data.logisticsMap ;
          param[str4] = res.data.data.goodsMap ;
          that.setData(param);
        } else {
          param[str1] = [];
          param[str3]= {};
          param[str4] = {};
          this.setData(param);
        }
      }
    })
  },
  orderDetail: function (e) {
    var orderId = e.currentTarget.dataset.id;
    wx.navigateTo({
      url: "/pages/order-details/index?id=" + orderId
    })
  },
  cancelOrderTap: function (e) {
    var that = this;
    var orderId = e.currentTarget.dataset.id;
    wx.showModal({
      title: '确定要取消该订单吗?',
      content: '',
      success: function (res) {
        if (res.confirm) {
          wx.showLoading();
          wx.request({
            url: app.globalData.baseUrl + '/order/close',
            data: {
              token: app.globalData.token,
              orderId: orderId
            },
            success: (res) => {
              wx.hideLoading();
              if (res.data.code == 0) {
                var param = {}, str = 'statusType[' + that.data.currentType + '].page';
                param[str]=0;
                that.getList();
              }
            }
          })
        }
      }
    })
  }
})

pages/order-list/index.wxss

.container{
    width: 100%;
    background-color: #F2f2f2;
}
.status-box{
    width:100%;
    height: 88rpx;
    line-height: 88rpx;
    display: flex;
    justify-content: space-between;
    align-items: center;
    background-color: #fff;
}
.status-box .status-label{
    width: 150rpx;
    height: 100%;
    text-align: center;
    font-size:28rpx;
    color:#353535;
    box-sizing: border-box;
    position: relative;
}
.status-box .status-label.active{
    color:#e64340;
    border-bottom: 6rpx solid #e64340;
}
.status-box .status-label .red-dot{
    width: 16rpx;
    height: 16rpx;
    position: absolute;
    left: 116rpx;
    top:23rpx;
    background-color: #f43530;
    border-radius: 50%;
}
.no-order{
    width: 100%;
    position: absolute;
    bottom: 0;
    top:0;
    left: 0;
    right: 0;
    text-align: center;
    padding-top: 203rpx;
    background-color: #F2f2f2;
}
.no-order-img{
    width: 81rpx;
    height: 96rpx;
    margin-bottom: 31rpx;
}
.no-order .text{
    font-size:28rpx;
    color:#999999;
    text-align: center
}
.order-list{
    width: 100%;
}
.order-list .a-order{
    width: 100%;
    background-color: #fff;
    margin-top: 20rpx;
}
.order-list .a-order .order-date{
    padding: 0 30rpx;
    height: 88rpx;
    display: flex;
    justify-content: space-between;
    font-size:26rpx;
    color:#000000;
    align-items: center;
}
.order-list .a-order .order-date .red{
    font-size:26rpx;
    color:#e64340;
}
.a-order  .goods-info,
.goods-img-container{
    width: 720rpx;
    margin-left: 30rpx;
    border-top: 1rpx solid #eee;
    border-bottom: 1rpx solid #eee;
    padding: 30rpx 0;
    display: flex;
    align-items: center;
}
.goods-info .img-box{
    width: 120rpx;
    height: 120rpx;
    overflow: hidden;
    margin-right: 30rpx;
    background-color: #f7f7f7;
}
.goods-info .img-box .goods-img,
.goods-img-container .img-box .goods-img{
    width: 120rpx;
    height: 120rpx;
}
.goods-info  .goods-des{
    width: 540rpx;
    height: 78rpx;
    line-height: 39rpx;
    font-size:26rpx;
    color:#000000;
    overflow: hidden;
}
.goods-img-container{
    height: 180rpx;
    box-sizing: border-box;
    white-space: nowrap;
}
.goods-img-container .img-box{
    width: 120rpx;
    height: 120rpx;
    overflow: hidden;
    margin-right: 20rpx;
    background-color: #f7f7f7;
    display: inline-block;
}
.order-list .a-order .price-box{
    position: relative;
    width: 720rpx;
    height: 100rpx;
    margin-left: 30rpx;
    box-sizing: border-box;
    padding: 20rpx 30rpx 20rpx 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size:26rpx;
}
.order-list .a-order .price-box .total-price{
    font-size:26rpx;
    color:#e64340;
}
.a-order .price-box .btn{
    width: 166rpx;
    height: 60rpx;
    box-sizing: border-box;
    text-align: center;
    line-height: 60rpx;
    border-radius: 6rpx;
    margin-left: 20rpx;
}
.a-order .price-box .cancel-btn{
    border: 1rpx solid #ccc;
    position: absolute;
    right: 216rpx;
    top:20rpx;
}
.a-order .price-box .topay-btn{
    border:1px solid #e64340;
    color: #e64340;
}

效果图
这里写图片描述

项目地址:https://github.com/hanxue10180/shangcheng

猜你喜欢

转载自blog.csdn.net/hanxue_tyc/article/details/78673172