§ 页面逻辑处理

本文配套视频地址:

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

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

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

  1. 微信小程序教学第二章:小程序中级实战教程之预备篇 - 项目结构设计 |基于最新版1.0开发者工具

    iKcamp官网:http://www.ikcamp.com 访问官网更快阅读全部免费分享课程:<iKcamp出品|全网最新|微信小程序|基于最新版1.0开发者工具之初中级培训教程分享>. ...

  2. 微信小程序教学第三章第四节(含视频):小程序中级实战教程:下拉更新、分享、阅读标识

    下拉更新.分享.阅读标识 本文配套视频地址: https://v.qq.com/x/page/h0554i4u5ob.html 开始前请把 ch3-4 分支中的 code/ 目录导入微信开发工具 这一 ...

  3. 微信小程序教学第三章第三节(含视频):小程序中级实战教程:视图与数据关联

    § 视图与数据关联 本文配套视频地址: https://v.qq.com/x/page/z0554wyswib.html 开始前请把 ch3-3 分支中的 code/ 目录导入微信开发工具 首先 首先 ...

  4. 微信小程序教学第四章第三节(含视频):小程序中级实战教程:详情-功能完善

    详情 - 功能完善 本文配套视频地址: https://v.qq.com/x/page/f0555nfdi14.html 开始前请把 ch4-3 分支中的 code/ 目录导入微信开发工具 这一节中, ...

  5. 微信小程序教学第四章第一节(含视频):小程序中级实战教程:详情-页面制作

    详情 - 页面制作 本文配套视频地址: https://v.qq.com/x/page/o0555o20xjd.html 开始前请把 ch4-1 分支中的 code/ 目录导入微信开发工具 这一章节中 ...

  6. 微信小程序教学第四章第二节(含视频):小程序中级实战教程:详情-视图渲染

    § 详情 - 数据渲染 本文配套视频地址: https://v.qq.com/x/page/x055550lrvd.html 开始前请把 ch4-2 分支中的 code/ 目录导入微信开发工具 这一节 ...

  7. 微信小程序教学第二章(含视频):小程序中级实战教程之预备篇 - 封装网络请求及 mock 数据

    § 封装网络请求及 mock 数据 本文配套视频地址: https://v.qq.com/x/page/i05544fogcm.html 开始前请把 ch2-3 分支中的 code/ 目录导入微信开发 ...

  8. java中的数据类型,运算符,字符串,输入输出,控制流,大数值,数组; 《java核心技术卷i》 第三章:java基本程序结构;

    <java核心技术卷i> 第三章:java基本程序结构: 每次看书,去总结的时候,总会发现一些新的东西,这次对于java的数组有了更深的了解: java中的数据类型,运算符,字符串,输入输 ...

  9. 【WePY小程序框架实战二】-页面结构

    [WePY小程序框架实战一]-创建项目 项目结构 |-- dist |-- node_modules |-- src | |-- components |-- a.wpy |-- b.wpy |-- ...

随机推荐

  1. How To Use Linux epoll with Python

    http://scotdoyle.com/python-epoll-howto.html Line 1: The select module contains the epoll functional ...

  2. 如何从零开始对接第三方登录(Java版):QQ登录和微博登录

    前言 个人网站最近增加了评论功能,为了方便用户不用注册就可以评论,对接了QQ和微博这2大常用软件的一键登录,总的来说其实都挺简单的,可能会有一点小坑,但不算多,完整记录下来方便后来人快速对接. 后台设 ...

  3. mysql 查询数据库内各表的占用大小

    select TABLE_NAME, concat(truncate(data_length/1024/1024,2),' MB') as data_size, concat(truncate(ind ...

  4. ionic开发遇到的坑及总结

    前言 ionic是一个用来开发混合手机应用的,开源的,免费的代码库.可以优化html.css和js的性能,构建高效的应用程序,而且还可以用于构建Sass和AngularJS的优化.ionic会是一个可 ...

  5. 一步一步教你用c# entity framework6 连接 sqlite 实现增删改查

    使用entity framework6 连接 SQLite 数据库 前言 很多小型应用程序中,都要使用数据库,而现在比较流行的本地数据库非SQLite莫属. 第一步:前期准备 开发环境:vs2015 ...

  6. input常见类型

       值   描述  text   默认.定义单行输入字段,用户可在其中输入文本.默认是 20 个字符  button   定义可点击的按钮(大多与 JavaScript 使用来启动脚本)  chec ...

  7. unity android相互调用

    简介 有一些手机功能,Unity没有提供相应的接口,例如震动,例如不锁屏,例如GPS,例如... 有太多的特殊功能Unity都没有提供接口,这时候,我们就需要通过使用Android原生的ADT编辑器去 ...

  8. java如何声明一个数组用来存储随机生成的字母并且保证不重复

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Monaco } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px ...

  9. php条件语句(二)

    switch 语句用于根据多个不同条件执行不同动作. PHP Switch 语句 如果您希望有选择地执行若干代码块之一,请使用 switch 语句. 语法 switch (n){case label1 ...

  10. 学习makefile的一个工程示例

    前言 makefile推荐资料为陈皓的跟我一起写makefile,需要pdf资源的可以私我 正文 工程目录结构 ---include(放置头文件.h) ------student.h(Student类 ...