微信小程序教学第三章(含视频):小程序中级实战教程:列表-页面逻辑处理

来源:互联网 发布:验证java安装成功 编辑:程序博客网 时间:2024/05/16 23:42

§ 页面逻辑处理

本文配套视频地址:
https://v.qq.com/x/page/n0554dndrez.html


开始前请把 ch3-2 分支中的 code/ 目录导入微信开发工具  


修改 index.js 文件,引入我们需要的外部资源

'use strict';import util from '../../utils/index';import config from '../../utils/config';let app = getApp();let isDEV = config.isDev;// 后继的代码都会放在此对象中let handler = {}Page(handler)


数据绑定

我们首先挖出和渲染相关的数据,并添加在 handler 对象的 data 字段中(Model 层)
修改 index.js 中的 handler 对象:

// 此处省略部分代码let handler = {  data: {    page: 1, //当前加载第几页的数据    days: 3,    pageSize: 4,    totalSize: 0,    hasMore: true,// 用来判断下拉加载更多内容操作    articleList: [], // 存放文章列表数据,与视图相关联    defaultImg: config.defaultImg  },}

注意: 后续添加的代码都是放在 handler 对象中,它会传递到 Page 函数中用来初始化页面组件

获取数据

然后要做的就是获取列表的数据,初始化数据的工作我们一般放在生命周期的 onLoad() 里:

let handler = {  onLoad (options) {    this.requestArticle()  },  /*   * 获取文章列表数据   */  requestArticle () {    util.request({      url: 'list',      mock: true,      data: {        tag:'微信热门',        start: this.data.page || 1,        days: this.data.days || 3,        pageSize: this.data.pageSize,        langs: config.appLang || 'en'      }    })    .then(res => {      console.log( res )      });  } }


数据加载完成之后,我们需要对接口返回的数据进行业务方面的容错处理

修改 requestArticle 函数:

let handler = {  // 此处省略部分代码  requestArticle () {    util.request({      url: 'list',      mock: true,      data: {        tag:'微信热门',        start: this.data.page || 1,        days: this.data.days || 3,        pageSize: this.data.pageSize,        langs: config.appLang || 'en'      }    })    .then(res => {      // 数据正常返回      if (res && res.status === 0 && res.data && res.data.length) {          // 正常数据 do something          console.log(res)      }       /*      * 如果加载第一页就没有数据,说明数据存在异常情况      * 处理方式:弹出异常提示信息(默认提示信息)并设置下拉加载功能不可用      */       else if (this.data.page === 1 && res.data && res.data.length === 0) {          util.alert();          this.setData({              hasMore: false          });      }       /*      * 如果非第一页没有数据,那说明没有数据了,停用下拉加载功能即可      */       else if (this.data.page !== 1 && res.data && res.data.length === 0) {          this.setData({              hasMore: false          });      }       /*      * 返回异常错误      * 展示后端返回的错误信息,并设置下拉加载功能不可用      */       else {          util.alert('提示', res);          this.setData({              hasMore: false          });          return null;      }    })  } }


上面我们把 wx.request 重新包装成了 Promise 的形式,其实我们是请求的 mock 数据。但是接口请求到的数据绝大部分情况下都不会直接适用于 UI 展示,所以我们需要做一层数据转换,把接口数据转换成视图数据。


格式化数据

先看下后端返回的数据结构

我们需要做两件事情
1. 遍历 data 数组,对返回的日期格式化,当天的显示 今天,如果是今年的文章,显示月日格式 08-21 ;如果是往年的文章,显示标准的年月日格式 2015-06-12
2. 遍历 articles 数组,判断此篇文章的 contentId 是否已经在全局变量 visitedArticles 中,如果存在,说明已经访问过。

修改 app.js,增加全局变量 visitedArticles

globalData: {  user: {    name: '',    avator: ''  },  visitedArticles: ''}


修改 index.js 中的 requestArticle 函数:

let handler = {  // 此处省略部分代码  requestArticle () {    // 注意:修改此处代码    if (res && res.status === 0 && res.data && res.data.length) {      let articleData = res.data;      //格式化原始数据      let formatData = this.formatArticleData(articleData);      console.log( formatData )    }   }}


增加对列表数据格式化的代码:

let handler = {  // 此处省略部分代码  /*  * 格式化文章列表数据  */  formatArticleData (data) {      let formatData = undefined;      if (data && data.length) {          formatData = data.map((group) => {              // 格式化日期              group.formateDate = this.dateConvert(group.date);              if (group && group.articles) {                  let formatArticleItems = group.articles.map((item) => {                      // 判断是否已经访问过                      item.hasVisited = this.isVisited(item.contentId);                      return item;                  }) || [];                  group.articles = formatArticleItems;              }              return group          })      }      return formatData;  },  /*  * 将原始日期字符串格式化 '2017-06-12'  * return '今日' / 08-21 / 2017-06-12  */  dateConvert (dateStr) {      if (!dateStr) {          return '';      }      let today = new Date(),          todayYear = today.getFullYear(),          todayMonth = ('0' + (today.getMonth() + 1)).slice(-2),          todayDay = ('0' + today.getDate()).slice(-2);      let convertStr = '';      let originYear = +dateStr.slice(0,4);      let todayFormat = `${todayYear}-${todayMonth}-${todayDay}`;      if (dateStr === todayFormat) {          convertStr = '今日';      } else if (originYear < todayYear) {          let splitStr = dateStr.split('-');          convertStr = `${splitStr[0]}年${splitStr[1]}月${splitStr[2]}日`;      } else {          convertStr = dateStr.slice(5).replace('-', '月') + '日'      }      return convertStr;  },  /*  * 判断文章是否访问过  * @param contentId  */  isVisited (contentId) {      let visitedArticles = app.globalData && app.globalData.visitedArticles || '';      return visitedArticles.indexOf(`${contentId}`) > -1;  },}


正常情况下,这个时候控制台打印出来的数据,是经过格式化的标准数据了,下一步,我们需要把它添加到 data 中的 articleList 字段里面,这样视图才有了渲染的数据


修改 index.js,增加 renderArticle 函数。由于每次请求的都是某一页的数据,所以在函数中,我们需要把每次请求过来的列表数据都 concat(拼接)到 articleList中:

let handler = {  // 此处省略部分代码  renderArticle (data) {      if (data && data.length) {          let newList = this.data.articleList.concat(data);          this.setData({              articleList: newList          })      }  }}


requestArticle 函数中调用 renderArticle:

let handler = {  // 此处省略部分代码  requestArticle () {    // 注意:修改此处代码    if (res && res.status === 0 && res.data && res.data.length) {      let articleData = res.data;      //格式化原始数据      let formatData = this.formatArticleData(articleData);      this.renderArticle( formatData )    }   }}


最终结果

最终的 index.js 文件就是这样的:

'use strict';import util from '../../utils/index'import config from '../../utils/config'let app = getApp()let isDEV = config.isDev// 后继的代码都会放在此对象中let handler = {  data: {    page: 1, //当前的页数    days: 3,    pageSize: 4,    totalSize: 0,    hasMore: true,// 用来判断下拉加载更多内容操作    articleList: [], // 存放文章列表数据    defaultImg: config.defaultImg  },  onLoad(options) {    this.requestArticle();  },  /*  * 获取文章列表数据  */  requestArticle() {    util.request({      url: 'list',      mock: true,      data: {        tag: '微信热门',        start: this.data.page || 1,        days: this.data.days || 3,        pageSize: this.data.pageSize,        langs: config.appLang || 'en'      }    })      .then(res => {        // 数据正常返回        if (res && res.status === 0 && res.data && res.data.length) {          let articleData = res.data;          //格式化原始数据          let formatData = this.formatArticleData(articleData);          this.renderArticle(formatData)        }        /*        * 如果加载第一页就没有数据,说明数据存在异常情况        * 处理方式:弹出异常提示信息(默认提示信息)并设置下拉加载功能不可用        */        else if (this.data.page === 1 && res.data && res.data.length === 0) {          util.alert();          this.setData({            hasMore: false          });        }        /*        * 如果非第一页没有数据,那说明没有数据了,停用下拉加载功能即可        */        else if (this.data.page !== 1 && res.data && res.data.length === 0) {          this.setData({            hasMore: false          });        }        /*        * 返回异常错误        * 展示后端返回的错误信息,并设置下拉加载功能不可用        */        else {          util.alert('提示', res);          this.setData({            hasMore: false          });          return null;        }      })  },  /*  * 格式化文章列表数据  */  formatArticleData(data) {    let formatData = undefined;    if (data && data.length) {      formatData = data.map((group) => {        // 格式化日期        group.formateDate = this.dateConvert(group.date);        if (group && group.articles) {          let formatArticleItems = group.articles.map((item) => {            // 判断是否已经访问过            item.hasVisited = this.isVisited(item.contentId);            return item;          }) || [];          group.articles = formatArticleItems;        }        return group      })    }    return formatData;  },  /*  * 将原始日期字符串格式化 '2017-06-12'  * return '今日' / 08-21 / 2017-06-12  */  dateConvert(dateStr) {    if (!dateStr) {      return '';    }    let today = new Date(),      todayYear = today.getFullYear(),      todayMonth = ('0' + (today.getMonth() + 1)).slice(-2),      todayDay = ('0' + today.getDate()).slice(-2);    let convertStr = '';    let originYear = +dateStr.slice(0, 4);    let todayFormat = `${todayYear}-${todayMonth}-${todayDay}`;    if (dateStr === todayFormat) {      convertStr = '今日';    } else if (originYear < todayYear) {      let splitStr = dateStr.split('-');      convertStr = `${splitStr[0]}年${splitStr[1]}月${splitStr[2]}日`;    } else {      convertStr = dateStr.slice(5).replace('-', '月') + '日'    }    return convertStr;  },  /*  * 判断文章是否访问过  * @param contentId  */  isVisited(contentId) {    let visitedArticles = app.globalData && app.globalData.visitedArticles || '';    return visitedArticles.indexOf(`${contentId}`) > -1;  },  renderArticle(data) {    if (data && data.length) {      let newList = this.data.articleList.concat(data);      this.setData({        articleList: newList      })    }  }}Page(handler)


下一篇中,我们将会把数据与视图层结合在一起,动态的展示视图层

iKcamp官网:http://www.ikcamp.com

访问官网更快阅读全部免费分享课程:《iKcamp出品|全网最新|微信小程序|基于最新版1.0开发者工具之初中级培训教程分享》。
包含:文章、视频、源代码

iKcamp原创新书《移动Web前端高效开发实战》已在亚马逊、京东、当当开售。

iKcamp最新活动

报名地址:http://www.huodongxing.com/event/5409924174200

“天天练口语”小程序总榜排名第四、教育类排名第一的研发团队,面对面沟通交流。

阅读全文
0 0
原创粉丝点击