§ 页面逻辑处理

本文配套视频地址:

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. Android Task 任务

    关于Android中的组件和应用,之前涉及,大都是静态的概念.而当一个应用运行起来,就难免会需要关心进程.线程这样的概念.在Android中,组件的动态运行,有一个最与众不同的概念,就是Task,翻译 ...

  2. linux使用yum安装mariadb

    一,安装 yum install mariadb mariadb-server 二,如何设置密码 用root 进入mysql后  mysql>set password =password('你的 ...

  3. 张高兴的 Xamarin.Forms 开发笔记:TapGestureRecognizer 的简单介绍与应用

    最近很少写应用了,一直在忙关于 ASP.NET 的东西(哈欠...).抽点时间对 TapGestureRecognizer 做点总结. 一.简介 TapGestureRecognizer 就是对 Ta ...

  4. 《Metasploit魔鬼训练营》第四章(上)

    p128 wmap 和昨天一样,我用这些漏洞扫描工具去扫testfire.net或者owaspbwa都扫不出漏洞!不明白! 补充:原来是网络不知道啥时候自己断了.连上后再次扫描就成功了:

  5. P3052 [USACO12MAR]摩天大楼里的奶牛Cows in a Skyscraper

    题目描述 给出n个物品,体积为w[i],现把其分成若干组,要求每组总体积<=W,问最小分组.(n<=18) 输入格式: Line 1: N and W separated by a spa ...

  6. Nginx简介与安装

    | 简介 Nginx是一个高性能的HTTP和反向代理服务器,可以作为负载均衡服务器,也是一个IMAP/POP3/SMTP服务器.它的特点是占有内存少,并发能力强.目前有很多大型公司都在使用Nginx, ...

  7. JavaScript正则表达式(Regular Expression):RegExp对象

    第一部分:新建正则表达式 JavaScript中正则表达式是参照Perl 5(一门历史很悠久的语言,现在tiobe编程语言排行依然在10名左右)建立的. 新建正则表达式的方法有两种: 1.使用字面量( ...

  8. Numpy数组对象的操作-索引机制、切片和迭代方法

    前几篇博文我写了数组创建和数据运算,现在我们就来看一下数组对象的操作方法.使用索引和切片的方法选择元素,还有如何数组的迭代方法. 一.索引机制 1.一维数组 In [1]: a = np.arange ...

  9. B2B电商系统开发建设的价格费用取决于哪些要素

    B2B电子商务系统平台建设开发怎么做?如何搭建一个电商系统网站平台?相信我们的企业商家在搭建电子商务系统的时候都会进行前期的系统策划,但是对于电子商务系统的构建绝大多数人都有一个误区,那就是对于电子商 ...

  10. Wannafly挑战赛3 record

    B 遇见 时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 65536K,其他语言131072K64bit IO Format: %lld题目描述A和B在同一条路上,他们之间的距离为 k ...