分享

开发|走进小程序(二)

 算法与编程之美 2020-08-08

前言

之前的博客《走进小程序》介绍了制作小程序的准备步骤和一些技术知识,这次我们从实际制作入手,边做边学。

由于小程序有许多的知识点,不能一一讲解,只能讲述一下思路然后,功能的实现,要用到什么就学习什么,这样比较会节省时间,提高效率。

我们这次要做的是一个电商类的微信小程序,下面就正式开始吧!

首页

首先要做的就是首页,一般电商的首页就是分为三大板块:轮播图、活动板块、首页列表。

大致效果如图:

大概步骤分为以下四步:

1、轮播图:根据接口数据生成banners,再用Wx:for 遍历banners生成swiper-item  ,最后在swiper标签里面渲染得到的数据。

2、整点限时抢购:Date对象,topList的数据作为抢购数据, scroll-view 做横向滚动,scroll-view的宽度是屏幕宽度,里面有一个容器,这个容器可以放下所有抢购的商品,就可以横向滚动了。(扩展:比如热销排行、明星产品、猜你喜欢,样式可以优化,不限于vant组件库)

3、首页商品列表:也是先从接口取到所有列表数据,然后利用vant组件里的van-card组件循环出商品列表。

4、上拉加载:默认start值为0,每一次滚动条拉到底部的时候,start+=20,请求接下来的20条数据,onReachBottom指的就是滚动条到达底部,把数据添加到list里,就可以显示所有数据了,在这里还用到了vanloading这个组件来告诉用户正在加载。

主要代码为:

1.js部分:

/**

   * 页面的初始数据

   */

  data: {

    imgUrls : [

      "/static/images/banner.jpeg",

      "/static/images/banner.jpeg"

    ],

    swiperWidth: 0, // 屏幕宽度

    swiperHeight  : 0, // 根据屏幕宽度等比例计算图片高度

    buyList : [], // 限时抢购的数据

    buyTime : "010226", // 限时抢购倒计时

    list: [], // 首页商品列表数据

    start : 0// 上拉加载的时候请求数据的起始点

  },

  /**

   * 生命周期函数--监听页面加载

   */

  onLoad: function (options) {

    // 请求服务器,得到首页的数据

    let _this = this;

    wx.request({

      url: 'http://www./api/tab/1',

      method : "get",

      success : function(res){

        console.log(res);

        _this.setData({

          imgUrls: res.data.data.banners,

          buyList: res.data.data.topList,

          list:  res.data.data.items.list.filter(function(item, index){

            // 返回值为true,那么当前item就会保留,否则就过滤掉

            return item.title != undefined;

          })

        })

      }

    })

    // 根据屏幕宽度计算图片大小

    let screenWidth =  wx.getSystemInfoSync().screenWidth;

    this.setData({

      swiperWidth: screenWidth,

      swiperHeight: screenWidth / 1080 * 400

    })

    // 调用倒计时方法

    this.calcBuyTime();

    // 每隔一秒调用一次函数

    setInterval(this.calcBuyTime, 1000);

  },

/**

   * 页面上拉触底事件的处理函数

   */

  onReachBottom: function () {

    var _this = this;

    // 每一次上拉加载都是在之前的基础上+20

    var st = this.data.start + 20;

    this.setData({

      start : st

    });

    wx.request({

      url: 'http://www./api/tab/1/feeds?start='+this.data.start,

      method : "GET",

      success : function (res) {

        // 过滤调没有title的数据

        var list =  res.data.data.list.filter(function (item) {

          // title属性就保留,没有就被过滤掉

          return item.title;

        });

        // 当前请求下来的list添加到datalist里面去

        var arr =  _this.data.list.concat(list);

        // ... 指的是把数组展开成一系列逗号隔开的值

        // var arr =  [2,3,4,5];

        // ...arr --  2,3,4,5

        // var arr =  [..._this.data.list, ...list];

        _this.setData({

          list :arr

        });

      }

    })

  },

  /**

   * 用户点击右上角分享

   */

  onShareAppMessage: function () {

  },

  calcBuyTime : function () {

    // 把时间调到下一个整点

    var date = newDate();

    var startTime =  date.getTime();

    date.setHours(date.getHours() + 1, 0, 0);

    var endTime =  date.getTime();

    var direction =  parseInt((endTime - startTime)/1000);

    var seconds =  direction % 60;

    var minutes =  (direction - seconds) / 60;

    // 默认事下一个整点,所以小时数就是0

    // 可以继续扩展,把小时数计算一下

    var str = "00" + (minutes >  9 ? minutes : "0"+minutes) + (seconds>9 ? seconds : "0"+seconds);

    this.setData({

      buyTime: str

    });

  },

  // 跳转详情页

  onDetail : function (evt) {

    console.log(evt);

    var id =  evt.currentTarget.dataset.id;

    wx.navigateTo({

      url: '/pages/detail/detail?id='+id

    })

  }

})

 2.json部分:

{

  "usingComponents": {

    "van-button": "/dist/button/index",

    "van-card": "/dist/card/index",

    "van-loading": "/dist/loading/index"

  }

}

//引入vant库的各种组件

 3.wxml部分

<viewclass='page'>

  <viewclass='search'>

    <view>搜索</view>

    <view>

      <navigatorurl='/pages/search/search'>搜索商品</navigator>

    </view>

  </view>

  <swiper

    indicator-dots="true"

    autoplay="true"

    interval="3000"

    duration="500"

    circular="true"

    style="width:{{swiperWidth}}px;  height:{{swiperHeight}}px"

  >

    <blockwx:for="{{imgUrls}}">

      <swiper-item>

        <imagesrc="{{item.imageUrl}}"class="slide-image"/>

      </swiper-item>

    </block>

  </swiper>

  <view>

    <viewclass='buy-head'>

      <textclass='buy-title'>整点限时抢购</text>

      <viewclass='buy-time'>

        <text>{{buyTime[0]}}</text>

        <text>{{buyTime[1]}}</text>

        <textclass='icon'></text>

        <text>{{buyTime[2]}}</text>

        <text>{{buyTime[3]}}</text>

        <textclass='icon'></text>

        <text>{{buyTime[4]}}</text>

        <text>{{buyTime[5]}}</text>

      </view>

    </view>

    <scroll-view

      scroll-x

      style="width:  {{swiperWidth}}px;"

    >

      <viewclass='buy-body'>

        <blockwx:for="{{buyList}}">

          <viewclass='buy-item'>

            <viewclass='buy-image'><imagesrc='{{item.image}}'mode='aspectFit'></image></view>

            <view><textclass="van-ellipsis">{{item.title}}</text></view>

            <view><textclass="buy-price">{{item.price}}</text></view>

          </view>

        </block>

      </view>

    </scroll-view>

  </view>

  <viewclass='list'>

    <blockwx:for="{{list}}">

      <van-card

        bindtap="onDetail"

        data-id="{{item.id}}"

        tag="{{item.couponValue}}"

        price="{{item.price}}"

        origin-price="{{item.originPrice}}"

        title="{{item.title}}"

        thumb="{{  item.image }}"

      >

        <viewslot="footer">

          <van-buttonsize="mini">查看详情</van-button>

          <van-buttonsize="mini"type='danger'>加购物车</van-button>

        </view>

      </van-card>

    </block>

  </view>

  <viewclass='loading'>

    <van-loadingtype="spinner"color="#fff"/>

  </view>

</view>

分类页

对于分类页的制作

1、请求所有分类title,显示在小程序顶部,使用vant组件库里的van-tabs组件。

2、默认第一个分类的数据请求下来然后做列表渲染

3、点击分类,绑定change事件,在事件里得到当前分类的索引值,通过索引值得到id请求当前分类的数据http://www./api/tab/  ” +id得到数据以后放在当前分类的detail

4、分类的上拉加载:因为不同的分类都有自己的数据,所以每一种分类都有自己的start,所以在tabList里面每一个对象都有默认start=0,下拉的时候把当前这个分类的start += 20,去请求下20条数据,添加到当前分类的detail里。 

具体代码为:

1.Js部分:

data: {

    tabList : [], // 分类的所有数据

    tabIndex : 0// 当前正在查看的分类在tabList里的索引

  },

  /**

   * 生命周期函数--监听页面加载

   */

  onLoad: function (options) {

    // 请求数据接口,得到tab列表

    var _this = this;

    wx.request({

      url: 'http://www./api/tabs',

      method: "GET",

      success : function(res){

        console.log(res);

        _this.setData({

          tabList : res.data.data.list.map(function(item){

            // 给每一个分类加上start默认值为0

            item.start = 0;

            return item;

          })

        });

        // 请求默认第一个分类的数据

        wx.request({

          url: 'http://www./api/tab/'+_this.data.tabList[0].id,

          method: "GET",

          success : function (res) {

            var list =  res.data.data.items.list;

            console.log(list);

            // tabList里有多个title,每个title都有自己对应的详细商品数据

            // 所以新增detail字段放到对应title的对象里

            // 由于小程序里直接修改data的值不会立即生效

            // 所以先取出来,修改完成以后再set回去

            var tabList =  _this.data.tabList;

            tabList[0].detail =  list.filter(function(item){

              // title存在,return true   title不存在,return false

              return item.title;

            });

            _this.setData({

              tabList : tabList

            });

          }

        })

      }

    })

onReachBottom: function () {

    var _this = this;

    // 得到当前分类的索引

    var idx = this.data.tabIndex;

    // 使用索引取到当前分类的id

    var id = this.data.tabList[idx].id;

    // tabList取出来,设置当前分类的starttabList  set回去

    var list = this.data.tabList;

    list[idx].start += 20;

    var start =  list[idx].start;

    this.setData({

      tabList : list

    });

    // 请求当前分类的下20条数据

    wx.request({

      url: 'http://www./api/tab/'+ id +'?start=' + start,

      method : "GET",

      success : function (res) {

        // 得到后20条数据

        // tabList的当前分类的detail里追加这20

        var list =  _this.data.tabList;

        list[idx].detail =  list[idx].detail.concat(res.data.data.items.list);

         console.log(res.data.data.items.list);

        _this.setData({

          tabList : list

        });

      }

    })

  },

  /**

   * 用户点击右上角分享

   */

  onShareAppMessage: function () {

  },

  onTabChange : function (evt) {

    var _this = this;

    // 得到当前分类的索引值,通过索引值取id

    // 通过当前id对应的接口去请求数据

    console.log(evt.detail);

    var idx =  evt.detail.index;

    // 修改当前tabIndex

    this.setData({

      tabIndex : idx

    });

    var id = this.data.tabList[idx].id;

    wx.request({

      url: 'http://www./api/tab/'+id,

      method: "GET",

      success : function (res) {

         console.log(res.data.data.items.list);

        // tabLIst取出来赋值给list,然后修改list[idx].detail

        // 修改结束以后再把整个tabList setData回去

        var list =  _this.data.tabList;

        list[idx].detail =  res.data.data.items.list;

        _this.setData({

          tabList : list

        });

      }

    })

  },

  onDetail: function (evt) {

    console.log(evt);

    var id =  evt.currentTarget.dataset.id;

    wx.navigateTo({

      url: '/pages/detail/detail?id=' + id

    })

  }

})

 2.json部分

{

  //引入组件

  "usingComponents": {

    "van-tab": "/dist/tab/index",

    "van-tabs": "/dist/tabs/index",

    "van-card": "/dist/card/index",

    "van-button": "/dist/button/index",

    "van-loading": "/dist/loading/index"

  }

}

 3.wxml部分:

<viewclass='page'>

  <van-tabsswipeableanimatedstickybind:change="onTabChange">

    <blockwx:for="{{ tabList  }}">

      <van-tabtitle="{{item.name}}">

        <blockwx:for="{{item.detail}}"wx:for-item="detail">

           <van-card

              bindtap="onDetail"

              data-id="{{detail.id}}"

              tag="{{detail.couponValue}}"

              price="{{detail.price}}"

              origin-price="{{detail.originPrice}}"

              title="{{detail.title}}"

              thumb="{{  detail.image }}"

            >

              <viewslot="footer">

                <van-buttonsize="mini">查看详情</van-button>

                <van-buttonsize="mini"type='danger'>加购物车</van-button>

              </view>

            </van-card>

        </block>

      </van-tab>

    </block>

  </van-tabs>

<viewclass='loading'>

    <van-loadingtype="spinner"color="#fff"/>

  </view>

</view>

总结

这些页面我都没有贴上.wxss的代码,因为大家喜欢的风格都不一样,样式自己调一下就好。其实这两个页面的逻辑都不是很难,主要就是从接口请求数据,然后自己把它渲染出来。主要是有些知识没学过,就不知道怎么弄,但是只要会用那些方法,这两个页面就没什么难度。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约