Android开发者for小程序(二)-网络请求-轮播-列表-跳转

前言

这篇文章开始我们就正式进入小程序的项目开发,这里主要功能包括:网络请求,轮播图,纵向列表,下拉刷新,上拉加载,item点击传值,页面跳转传值.

效果图

效果图.gif

文件结构

配置

可以看到只有两个页面-index和info,所以在app.json中配置两个页面路径(注意该文件不能有注释)

{
  "pages": [
    "pages/index/index",
    "pages/info/info"
  ],
  "window": {
    "enablePullDownRefresh": true,
    "backgroundTextStyle": "dark",
    "navigationBarBackgroundColor": "#000",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle": "white"
  }
}

列表页面需要下拉刷新,所以在index.json中开启下拉刷新,在info中关闭下拉刷新,同时设置title

//index.json
{
    "navigationBarTitleText": "小程序",
    "enablePullDownRefresh": true
}
//info.josn
{
    "navigationBarTitleText": "详情页",
    "enablePullDownRefresh": false
}

页面

轮播图

轮播图由wx:for和<swiper-item>配合使用,wx:for="{{banners}}"指定数据源数组,interval="1000"指定自动切换的间隔,item为当前项的数据,index为下标,banners为js中的数据源,当js调用setdata并改变banners时,轮播图会刷新

<swiper class="swiper" indicator-dots="true" autoplay="true" interval="3000">
  <block wx:for="{{banners}}">
    <swiper-item>
      <image src="{{item.url}}" class="slide-image" mode="aspectFill" bindtap="itemClick" id="{{index}}" />
    </swiper-item>
  </block>
</swiper>
  • swiper组件提供一些属性,如自动切换,时间间隔,指示器等等

纵向列表

小程序不直接提供列表组件(如Android中的ListView,RecycleView),需要通过wx:for="{{listData}}来重复渲染形成列表,原理同样也是绑定数组,数组更新时刷新列表

    <view class="list">
      <block wx:for="{{listData}}">
        <view class="list-item">
          <image src=" {{item.url}} " class="item-image" mode="aspectFill" bindtap="itemClick" id=" {{index}}"/>
          <view class="item-text">
            <text class="item-title ">{{item.type}}</text>
            <view class="item-msg ">
              <text class="item-title ">{{item.who}}</text>
              <text class="item-title ">{{item.desc}}</text>
            </view>
          </view>
        </view>
      </block>
    </view>
  • 列表同样使用for来重复渲染,不同的是不需要<swiper-item>来包裹
  • 可以使用wx:key="_id"来指定item的唯一性,如果不指定,微信会抛一个警告,但不会影响程序运行,具体wx:key的原理可查看官方文档
  • 建议动态列表指定wx:key,这样效率会比较高,并且不会丢失item中的状态

数据

轮播图需要一个数组,列表需要一个数组,还需要记录当前页面,所以index的data部分:

Page({
  data: {
    banners: [],//轮播图数据源,
    pageNum: 1,//当前页码
    listData: []//列表数据
    }
)}

这里使用gank.io的api拉取数据用于轮播图和列表,由于下拉和上拉都需要用到该请求,故提取为方法以便复用
,返回数据的格式:

{
  "error": false,
  "results": [
    {
      "_id": "587c6073421aa91194ca0e2c",
      "createdAt": "2017-01-16T13:56:03.417Z",
      "desc": "1-16",
      "publishedAt": "2017-01-16T14:12:18.71Z",
      "source": "chrome",
      "type": "福利",
      "url": "http://ww3.sinaimg.cn/large/610dc034gw1fbsfgssfrwj20u011h48y.jpg",
      "used": true,
      "who": "daimajia"
    },
    {
      "_id": "5878471d421aa9119735ac13",
      "createdAt": "2017-01-13T11:18:53.183Z",
      "desc": "1-13",
      "publishedAt": "2017-01-13T11:58:16.991Z",
      "source": "chrome",
      "type": "福利",
      "url": "http://ww3.sinaimg.cn/large/610dc034gw1fbou2xsqpaj20u00u0q4h.jpg",
      "used": true,
      "who": "daimajia"
    }
  ]
}

index.js数据处理

//获取应用实例
var app = getApp()
Page({
  data: {
    banners: [],//轮播图数据源,
    pageNum: 1,//当前页码
    listData: []//列表数据
  },
  requestData() {
    var that = this
    wx.request({
      url: 'http://gank.io/api/data/福利/10/1',
      success: function (res) {//更新数据刷新UI
        banners: res.data.results,
        listData: res.data.results
      },
      fail: function () {

      },
      complete: function () {
        
      }
    })
  },
  onLoad: function () {
    this.requestData();
  }
})

下拉刷新和底部自动加载

ok,经过上面的一些步骤,我的小程序已经可以顺利运行并展示动态数据了,但是列表一般会配套刷新和分页加载,在小程序中这两个操作同样也是有提供的:

  • onPullDownRefresh为下拉的处理函数,
  • wx.stopPullDownRefresh()可以在请求完成后关闭拉下刷新,
  • onReachBottom为滑动到底部的处理函数,可用来做上拉加载分页

在index.json中配置开启了下拉刷新后,在index.js中处理对应事件:

Page({
  onReachBottom: function () {//底部自动加载
    this.data.pageNum++;
    this.requestData();
  },
  onPullDownRefresh: function () {//下拉刷新
    this.data.pageNum = 1;
    this.requestData();
}
  • 加载过程是耗时的,故需要给用户一些loading
  • 另外现在轮播和列表使用的是同一个请求,但是轮播实际永远只需要展示第一页的数据(图片)就可以了,所以也需要做下数据处理,
  • 网络请求出错应该给用户对应的提示

综合以上,则index.js(即逻辑层)最后的代码如下:

//index.js
//获取应用实例
var app = getApp()
Page({
  onReachBottom: function () {
    this.data.pageNum++;
    this.requestData();
  },
  onPullDownRefresh: function () {
    this.data.pageNum = 1;
    this.requestData();
  },
  data: {
    banners: [],//轮播图数据源,
    pageNum: 1,//当前页码
    listData: []//列表数据
  },
  requestData() {
    var that = this
    console.log("当前页码" + this.data.pageNum)
    if (that.data.listData.length < 1) {//第一次进来展示加载框
      wx.showToast({
        title: '加载中',
        icon: 'loading',
        duration: 500
      })
    } else {
      wx.showNavigationBarLoading()
    }
    wx.request({
      url: 'http://gank.io/api/data/福利/10/' + this.data.pageNum,
      success: function (res) {
        console.log("请求成功" + res)
        wx.stopPullDownRefresh()//停止下拉刷新动画
        if (that.data.pageNum == 1) {
          that.data.listData = []//清空数组
        }
        var list = that.data.listData;
        for (var i = 0; i < res.data.results.length; i++) {
          list.push(res.data.results[i]);
        }
        that.setData({
          listData: list,//更新数据
          banners: that.data.listData.slice(0,Math.min(9, that.data.listData.length))//截取数组
        })
        // success
      },
      fail: function () {
        wx.showModal({
          title: '加载出错',
          showCancel: false
        })
      },
      complete: function () {//加载完成
        wx.hideToast()
        wx.hideNavigationBarLoading()
      }
    })
  },
  onLoad: function () {
    this.requestData();

  }
})
  • 轮播和列表数据分开使用两个数组存储,其中轮播为列表的第一页数据
  • 由于success内部环境为wx.request,故this相当于wx.request这个对象(js中,函数也是对象),对于Android开发者这一点是非常好理解的(相当于Android中的内部类),故需要在外面使用临时变量存储var that = this,这样使用that则是指向page
  • 用到一些js的数据操作:that.data.listData = []//清空数组 ; list.push(res.data.results[i]);//数组添加数据 ; that.data.listData.slice(0,Math.min(9, that.data.listData.length))//截取数组;

点击跳转

点击轮播图或者列表中的item需要到对应的详情页,展示该项的详情信息,分为两个步骤:

列表点击传值

即处理itemClick,并且需要获取到该项的数据(banners[index]),所以在点击事件中需要附带当前的下标-index;
小程序提供两种事件中传值的方式:

1.使用组件通用属性传值,如id(适用于少量数据)

//wxml
<swiper class="swiper" indicator-dots="true" autoplay="true" interval="3000">
  <block wx:for="{{banners}}">
    <swiper-item>
      <image src="{{item.url}}" class="slide-image" mode="aspectFill" bindtap="itemClick" id="{{index}}" />
    </swiper-item>
  </block>
</swiper>

//js
itemClick: function (event) {
  console.log(event)
  var index = event.target.id
},

2.使用事件中的dataset字段(适用于数据比较多)

//wxml
<swiper class="swiper" indicator-dots="true" autoplay="true" interval="3000">
  <block wx:for="{{banners}}">
    <swiper-item>
      <image src="{{item.url}}" class="slide-image" mode="aspectFill" bindtap="itemClick" data-index="{{index}}" />
    </swiper-item>
  </block>
</swiper>

//js
itemClick: function (event) {
  console.log(event)
  var index =  event.target.dataset.index
},
  • dataset中的key使用data-keyName固定格式指定,并且大写会被转为小写,在取值的时候则使用转化后的驼峰命名形式的key(很奇葩,不得不吐槽一下)

跳转传值

ok,item的点击事件和下标处理完成,接下来就是跳转详情页了,那么小程序中跳转应该怎么附带参数呢,在详情页又该怎么取值呢?还是看代码:

itemClick: function (event) {
  console.log(event)
  var index = event.target.id//取事件中附带的index值
  var item = this.data.listData[index]
  wx.navigateTo({//跳转
    url: '../info/info?title=' + item.desc + "&imageUrl=" + item.url + "&resType=" + item.type + "&source=" + item.who
  })

},

首先,从动点击事件的参数中取到index,从而从数组中取到item数据,最后使用wx.navigateTo跳转页面,该api需要指定跳转页面的路径,参数以key=value形式拼接在路径中(对于Android开发者是比较好理解的,这种形式与get请求参数拼接一致)

取值也非常简单,只需要在详情页的onLoad方法中取参数里的值即可,

//info.js
Page({
    data: {
        title: '',
        imageUrl: '',
        resType: '',
        source: ''
    },
    onLoad: function (res) {//取值
        wx.setNavigationBarTitle({//动态设置当行栏标题
            title: res.title
        })
        this.setData({//取值并更新数据和UI
            title: res.title,
            imageUrl: res.imageUrl,
            resType: res.resType,
            source: res.source,
        })
    }
})
  • 页面的参数传递全部需要key=value拼接的形式,在Android中是可以直接传递序列化对象的,但是小程序中好像并没有提供传递对象的方式;
  • 并且所有的参数都必须是String类型,其他类型内部均会自动转为String传递,这一点也需要注意一下

ok,所有Demo中涉及到的内容基本都提到了,没有什么特别难的点,有些地方开发思路需要做一下转变,注意一下细节(小程序比较封闭,代码书写方式也很严格).下一篇会是进阶的内容,包括Tab页面,视频播放

才疏学浅,还请大家及时指出博客中的问题,不慎感激.源码github

关于作者

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容