§ 页面逻辑处理

本文配套视频地址:

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. Python中__new__和__init__区别

    __new__:创建对象时调用,会返回当前对象的一个实例 __init__:创建完对象后调用,对当前对象的一些实例初始化,无返回值 1.在类中,如果__new__和__init__同时存在,会优先调用 ...

  2. 第2篇 C#数据类型-值类型与引用类型

    一 C#内存分配 在应用程序与操作系统之间有一个"中间人"--公共语言运行时(Common Language Runtime,CLR).它为应用程序提供内`存管理,线程管理和远程处 ...

  3. final、static、代码块、静态代码块、内部类、代码执行顺序

    final final域使得确保初始化安全性(initialization safety)成为可能,初始化安全性让不可变形对象不需要同步就能自由地被访问和共享 作用在类上               ...

  4. 【机器学习】DNN训练中的问题与方法

    感谢中国人民大学的胡鹤老师,人工智能课程讲的很有深度,与时俱进 由于深度神经网络(DNN)层数很多,每次训练都是逐层由后至前传递.传递项<1,梯度可能变得非常小趋于0,以此来训练网络几乎不会有什 ...

  5. sql 触发器,看完后对CHK有更深的理解

    触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程.触发器主要是通过事件进行触发被自动调用执行的.而存储过程可以通过存储过程的名称被调用. 什么是触发器? 触发器对表进行插入.更新.删除 ...

  6. 《java.util.concurrent 包源码阅读》10 线程池系列之AbstractExecutorService

    AbstractExecutorService对ExecutorService的执行任务类型的方法提供了一个默认实现.这些方法包括submit,invokeAny和InvokeAll. 注意的是来自E ...

  7. VMware中克隆虚拟机出现eth0改变为eth1情况

    解决如下: 查看复制虚拟机网卡信息如下: root@jcfx-2 ~]# ifconfig eth1 Link encap:Ethernet HWaddr 00:0C:29:CC:32:63 inet ...

  8. memcache调整value大小限制

    > *事件背景: 当Redis有问题时按预案就会切换到本机memcache,但是我们首页 key:value现 在是1.5M同时memcache item限制是1M,导致首页写入memcache ...

  9. 使用fastdfs-zyc监控FastDFS文件系统

    1.安装jdk运行环境 jdk下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html 此处我使用的jdk7U99 ...

  10. Netty4 学习笔记之四: Netty HTTP服务的实现

    前言 目前主流的JAVA web 的HTTP服务主要是 springMVC和Struts2,更早的有JSP/servlet. 在学习Netty的时候,发现Netty 也可以作HTTP服务,于是便将此整 ...