微信小程序-华为商城demo

2,704 阅读7分钟

最近在学习微信小程序,看了很多相关文档,以及一些大佬的文章,决定来练练,下面是仿照华为商城来实现其相应功能。代码没有很高深的地方,适合小程序初学者来相互学习借鉴。

前期准备

  • 有html、css、javascript基础,了解es6的一些语法,知道小程序开发步骤,详见微信小程序开发文档

  • 如果你想很完整的把一个项目仿照下来,一些图片资源是必不可少的,那么如何获取图片资源呢?这里我看到大佬的一篇文章 两步快速获取微信小程序源码 可以获取到 源码和图片,具体操作步骤就不一一解释了,作者写的很清楚。当然像我这样的菜鸟源码还是看不太懂的,只能用它的一些图片资源。不过有了这些图片我已经相当满足了,哈哈。。。

  • 有了图片还需要数据,利用easy-mock制作假数据,可以自己把需要的数据写下来,那么怎么获取这些数据呢,最简单的方法就是直接通过wx.request请求数据,不过一般都会对这个方法进行封装,下面来看看最简单的数据请求

onReady: function () {
    wx.request({
      url:'https://www.easy-mock.com/mock/5b122f9f8cd63333d30a6c8b/mobile',
      success:(res)=>{
         this.setData({
          theme:res.data
         })
        //  console.log(res.data);
      }    
    })
  }

关于功能

下面就来说说我的一些功能实现吧

首页效果

首页实现方式很简单,不过需要注意:

  • 在html中
    1. scroll-view竖向滚动必须设置scroll-y="true" style="height: 200rpx;" 必须..
    2. style="height: 200rpx;" 必须为200rpx/200px 不能用百分号
  • 在js中
    1. "toView","scrollTop"必须设置值
    2. "scrollTop": 0,必须为数值

详情页介绍

详情页数据信息比较多,主要实现各个功能的数据绑定

  • 功能一

图片滑动时,图片右下角数字会根据图片滑动改变,同时选择颜色时,图片会滑到对应项,主要实现思路:

主要监听swiper属性current的改变,绑定bindchange事件,举例说明

//index.html
<swiper class='sw-tu' circular="true" current="0" bindchange='onSlideChangeEnd'>  
  <swiper-item class="sw-tuone" wx:for="{{list.img2}}">  
    <image class='sw-photo' src="{{item}}" />  
  </swiper-item>  
</swiper>  

//index.js
data: {  
    index: 1,  
  },  
  onSlideChangeEnd: function (e) {  
    var that = this;  
    that.setData({  
      index: e.detail.current + 1  
    })  
  },  
  • 功能二

根据你选择的商品属性跳转到订单页,同时计算商品总价,通过url带参数把数据传递到订单页

 <view class="num">
    <text>数量</text>
    <view class="count-content">
         <view class="count-down {{grey?'on':''}}" bindtap="minusCount" data-index="{{index}}">-</view>
        <view class="count-num">{{num}}</view>
        <view class="count-add {{grey1?'on':''}}" bindtap="addCount" data-index="{{index}}">+</view>
    </view> 
</view>

 // 购买数量减
  minusCount(){
    let num = this.data.num;
    if(num <= 2){
      this.setData({
        grey:true,   //当数量到一时就不能再减少了,按钮变成灰色
        num:1
      })
      return;
    }
    num--;
    this.setData({
      grey:false,    
      grey1:false,
      num,
      totalPrice:this.data.onePrice*num  //计算总价
    })
  },
  // 购买数量加
  addCount(){
    let num = this.data.num;
    let totalNum = this.data.product[0].num;
    console.log(totalNum);
    if(num >= totalNum){
      this.setData({
        grey1:true,             //到商品库存量时不能再增加
        totalPrice:this.data.onePrice*num
      })
      return;
    }
    num++;
    this.setData({
      num,
      grey:false,
      grey1:false,
      totalPrice:this.data.onePrice*num
    })
  },
  //点击立即购买按钮,将所选择的参数传递到订单页面
  primary(){
    wx.navigateTo({
      url: `/pages/order/order?num=${this.data.num}&title=${this.data.product[0].title}&price=${this.data.product[0].price}&totalPrice=${this.data.totalPrice}`
    })
  },
  • 功能三

可以点击顶部评价进入评论页面,也可以点击商品页中的用户评价进入,评论页主要实现上拉加载功能

 <view wx:for="{{comments}}" wx:key="index" class="user_comment">
       <view class="user_info">
        <image class="avatar" src="{{item.avatar}}"/>
        <view class="tel">{{item.tel}}</view>
        <view class="star">
            <image src="/image/icon_star_red.png"></image>
            <image src="/image/icon_star_red.png"></image>
            <image src="/image/icon_star_red.png"></image>
            <image src="/image/icon_star_red.png"></image>
            <image
            src="/image/icon_star_red.png"></image>
        </view>
       </view> 
       <view class="content">{{item.content}}</view>
       <view class="time">{{item.time}}</view>
     </view>
    <view class="loading" hidden="{{noLoading}}">
    上拉加载更多评论</view>
    <image class="loadingImage"src="/image/loading.gif" hidden="{{noLoadingImage}}"></image>
     <view class="no-more" hidden="{{hasMore}}">暂时没有更多评论</view>
 onReachBottom(){
    let {currentPage,totalPage,noLoading,noLoadingImage}=this.data;
    //利用es6语法解构赋值
    // console.log(currentPage,totalPage,noLoading,noLoadingImage);
    if(currentPage >= totalPage){
      this.setData({
        hasMore:false
      })
      return;
    }
    currentPage ++;
    this.setData({
      noLoading:false,
      noLoadingImage:false
    })
    wx.request({
      url: 'https://www.easy-mock.com/mock/5b129d3c791ed91ba99b116c/detail',
      success: (res)=>{
        const comments =[...this.data.comments,...res.data.comments]; 
        this.setData({
          comments,
          noLoading:true,
          noLoadingImage:true,
          currentPage
        })
      }   
    })
  }

cuurentpage即为当前请求数据时第几页,每请求一次currentPage++,totalpage表示总页数,hasMore用于显示暂时没有评论了,noLoading由于显示上拉加载更多评论。当我们网络请求数据成功后,将currentPage设为1,当currentPage<totalPage时,noLoading设为false,显示上拉加载更多数据,当currentPage>totalPage是显示没有更多数据可以加载,noLoading为true,hasMore为false显示没有更多评论。

地址信息管理

主要实现对地址的增加修改和删除功能

利用表单实现对输入数据的提交,注意表单每项都要有name属性才能获取到表单数据,同时提交表单时对各项数据进行校验

formSubmit: function(e) {
    var warn ="";
    var that = this;
    var flag = false;
    if(!e.detail.value.name){
      warn = "请填写您的姓名!";
    }else if(!e.detail.value.tel){
      warn = "请填写您的手机号!";
    }else if(!(/^1(3|4|5|7|8)\d{9}$/.test(e.detail.value.tel))){
      warn = "手机号格式不正确";
    }else if(!e.detail.value.addre){
      warn = "请选择您的所在区域";
    }else if(!e.detail.value.door){
      warn = "请输入您的具体地址";
    }else{
      flag=true;
        wx.redirectTo({
        url: '../addressList/addressList?tel='+e.detail.value.tel+"&addre="+that.data.addreRange[e.detail.value.addre]+"&door="+e.detail.value.door+"&name="+e.detail.value.name+"&flag="+flag+"&addrevalue="+e.detail.value.addre
        //后面跟的是需要传递到下一个页面的参数

      }); 
        //  console.log("传过去的地址下标是多少?"+e.detail.value.addre)
    }
    if(flag==false){
      wx.showModal({
      title: '提示',
      content:warn
    })
    }
    
  },

在订单列表项可以点击右边的修改项,进入修改列表,在修改项中通过订单列表中传递过来的数据可以选择修改、删除或者保存地址

//获取传过来的数据
 onLoad: function(options) {
    this.setData({
      name:options.name,
      tel:options.tel,
      addreValue:options.addrevalue,
      door:options.door,
      index:options.index
    })
  },

关于地区选择,利用picker组件实现

//html
<view class="item">
    <text>所在地区</text>
    <view class="right">
        <picker name="addre" class="addre" value="{{addreValue}}" range="{{addreRange}}" bindchange="addrePickerBindchange">
            {{addreRange[addreValue]}}
        </picker>
    </view>
</view>

//js
data:{
    addreValue:0,
    addreRange:[江西省赣州市','江西省南昌市','江西省上饶市','江西省抚州市','江西省宜春市','江西省九江市'],
 }
 addrePickerBindchange:function(e){
    this.setData({
      addreValue:e.detail.value  //获取数组下标,最后把下标放入addreRange[e.detail.value.addre],取得值
})

订单列表项需要判断是从哪个选项跳转过来的,如果是删除项,则需要获取删除项的下标,利用数组的splice方法删除如果是从修改项过来,同样需要获取的修改项的下标,同时修改的数据也需要传递过来

//订单列表项
var index = 0;
var list=[];

Page({
  data:{
    list:[],
  },
  onLoad: function(options) {
    var flag=false;//判断是从哪个页面跳转过来
    var sign = 0//判断从修改页面中的保存还是删除按钮过来,保存为1,删除为2
    flag =options.flag;
    sign = options.sign;
    if (flag) {
      list.push({
      "index":index++,
      "name":options.name,
      "tel":options.tel,
      "addre":options.addre+options.door,
      "image":"../../image/uncheck.png",
      "addrevalue":options.addrevalue,
      "door":options.door
      })
      this.setData({
        list
      })
    };
    if(sign=='1'){
      // console.log("我是从修改页面过来的"+options.addrevalue)
      list[options.index].name=options.name;
      list[options.index].tel=options.tel;
      list[options.index].addre=options.addre+options.door;
      list[options.index].addrevalue=options.addrevalue;
      list[options.index].door=options.door;
      this.setData({
          list
        })
    };
    // 删除页面过来
    if(sign=='2'){
        list.splice(options.index, 1);
        this.setData({
          list
        })
      }
  },
  addAddre:function(e){
      wx.navigateTo({
        url: '../addressAdd/addressAdd'
      })
    },
  toModifyAddre:function(e){
    // console.log("选中的电话"+e.currentTarget.dataset.addrevalue);
    // console.log("选中的index"+e.currentTarget.dataset.index)
    wx.navigateTo({
      url: '../addressEdit/addressEdit?name='+ e.currentTarget.dataset.name+"&tel="+e.currentTarget.dataset.tel+"&addrevalue="+e.currentTarget.dataset.addrevalue+"&door="+e.currentTarget.dataset.door+"&index="+e.currentTarget.dataset.index
    })
  },
  toSelectAddr:function(e){
    for(var i = 0;i<this.data.list.length;i++){
      if(i==e.currentTarget.dataset.index){
      list[e.currentTarget.dataset.index].image = "../../image/radio_selected.png"}
      else{
        list[i].image = "../../image/uncheck.png"
      }
    }
    wx.navigateTo({
      url: '../order/order?name='+ e.currentTarget.dataset.name+"&tel="+e.currentTarget.dataset.tel+"&addre="+e.currentTarget.dataset.addre+"&flag="+true
    });
  }
 
})

最后知识总结

  • 关于页面传值,方法各异,具体实例请点击这里

    1. wx.navigateTo和wx.redirectTo通过url带参传递数据
    2. wx.switchTab进行跳转,但是switchTab不可以传递url参数,后面提供了wx.reLaunch函数。
    3. wx.getStorage获取本地缓存数据
    4. 在app.js配置全局数据app.globalData获取全局数据
    5. wx.request获取第三方服务器数据
    6. 通过event.currentTarget.dataset获取我们自定义的变量
    7. 接收上一页面传递过来的数据的页面通过onLoad事件的options参数接收数据
  • 数据缓存 实例请点击这里

    1. wx.setStorage(wx.setStorageSync)来设置缓存
    2. wx.getStorage(key) 获取缓存
    3. wx.clearStorage() 清理本地数据缓存
    4. wx.removeStorage(OBJECT) 从本地缓存中异步移除指定 key
    5. localStorage 是永久存储的

小程序还有很多不足,见谅哈~

写得不好,也留个赞呗

请点击我的github地址,里面有完整代码可供参考