微信小程序教学第三章(含视频):小程序中级实战教程:列表-页面逻辑处理
2017-10-25 00:00
1066 查看
摘要: ## <a>§ 页面逻辑处理</a>
> 本文配套视频地址:
> https://v.qq.com/x/page/n0554dndrez.html
---
> 开始前请把 `ch3-2` 分支中的 `code/` 目录导入微信开发工具
<br>
### 修改 `index.js` 文件,引入我们需要的外部资源
https://v.qq.com/x/page/n0554dndrez.html
开始前请把
<br>
修改
<br>
修改
注意: 后续添加的代码都是放在
<br>
<br>
<br>
上面我们把
<br>
我们需要做两件事情
遍历
遍历
修改
<br>
修改
<br>
增加对列表数据格式化的代码:
<br>
正常情况下,这个时候控制台打印出来的数据,是经过格式化的标准数据了,下一步,我们需要把它添加到
<br>
修改
<br>
在
<br>
<br>
下一篇中,我们将会把数据与视图层结合在一起,动态的展示视图层
iKcamp官网:http://www.ikcamp.com
访问官网更快阅读全部免费分享课程:《iKcamp出品|全网最新|微信小程序|基于最新版1.0开发者工具之初中级培训教程分享》。
包含:文章、视频、源代码
iKcamp原创新书《移动Web前端高效开发实战》已在亚马逊、京东、当当开售。
报名地址:http://www.huodongxing.com/event/5409924174200
与
> 本文配套视频地址:
> https://v.qq.com/x/page/n0554dndrez.html
---
> 开始前请把 `ch3-2` 分支中的 `code/` 目录导入微信开发工具
<br>
### 修改 `index.js` 文件,引入我们需要的外部资源
<a>§ 页面逻辑处理</a>
本文配套视频地址:https://v.qq.com/x/page/n0554dndrez.html
开始前请把
ch3-2分支中的
code/目录导入微信开发工具
<br>
修改 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)
<br>
数据绑定
我们首先挖出和渲染相关的数据,并添加在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函数中用来初始化页面组件
<br>
获取数据
然后要做的就是获取列表的数据,初始化数据的工作我们一般放在生命周期的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 ) }); } }
<br>
数据加载完成之后,我们需要对接口返回的数据进行业务方面的容错处理
修改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; } }) } }
<br>
上面我们把
wx.request重新包装成了
Promise的形式,其实我们是请求的 mock 数据。但是接口请求到的数据绝大部分情况下都不会直接适用于
UI展示,所以我们需要做一层数据转换,把接口数据转换成视图数据。
<br>
格式化数据
先看下后端返回的数据结构我们需要做两件事情
遍历
data数组,对返回的日期格式化,当天的显示
今天,如果是今年的文章,显示月日格式
08-21;如果是往年的文章,显示标准的年月日格式
2015-06-12。
遍历
articles数组,判断此篇文章的
contentId是否已经在全局变量
visitedArticles中,如果存在,说明已经访问过。
修改
app.js,增加全局变量
visitedArticles
globalData: { user: { name: '', avator: '' }, visitedArticles: '' }
<br>
修改
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 ) } } }
<br>
增加对列表数据格式化的代码:
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; }, }
<br>
正常情况下,这个时候控制台打印出来的数据,是经过格式化的标准数据了,下一步,我们需要把它添加到
data中的
articleList字段里面,这样视图才有了渲染的数据
<br>
修改
index.js,增加
renderArticle函数。由于每次请求的都是某一页的数据,所以在函数中,我们需要把每次请求过来的列表数据都
concat(拼接)到
articleList中:
let handler = { // 此处省略部分代码 renderArticle (data) { if (data && data.length) { let newList = this.data.articleList.concat(data); this.setData({ articleList: newList }) } } }
<br>
在
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 ) } } }
<br>
最终结果
最终的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)
<br>
下一篇中,我们将会把数据与视图层结合在一起,动态的展示视图层
iKcamp官网:http://www.ikcamp.com
访问官网更快阅读全部免费分享课程:《iKcamp出品|全网最新|微信小程序|基于最新版1.0开发者工具之初中级培训教程分享》。
包含:文章、视频、源代码
iKcamp原创新书《移动Web前端高效开发实战》已在亚马逊、京东、当当开售。
iKcamp最新活动
报名地址:http://www.huodongxing.com/event/5409924174200
与
“天天练口语”小程序总榜排名第四、教育类排名第一的研发团队,面对面沟通交流。
相关文章推荐
- 微信小程序教学第三章(含视频):小程序中级实战教程:列表-页面逻辑处理
- 微信小程序教学第三章(含视频):小程序中级实战教程:列表-静态页面制作
- 微信小程序教学第三章(含视频):小程序中级实战教程:列表-静态页面制作
- 微信小程序教学第四章第一节(含视频):小程序中级实战教程:详情-页面制作
- 微信小程序教学第四章第一节(含视频):小程序中级实战教程:详情-页面制作
- 微信小程序教学第四章第三节(含视频):小程序中级实战教程:详情-功能完善
- 微信小程序教学第二章(含视频):小程序中级实战教程之预备篇 - 封装网络请求及 mock 数据
- 微信小程序教学第四章第二节(含视频):小程序中级实战教程:详情-视图渲染
- 微信小程序教学第三章第四节(含视频):小程序中级实战教程:下拉更新、分享、阅读标识
- 微信小程序教学第三章第三节(含视频):小程序中级实战教程:视图与数据关联
- 微信小程序教学第四章第二节(含视频):小程序中级实战教程:详情-视图渲染
- 微信小程序教学第四章第三节(含视频):小程序中级实战教程:详情-功能完善
- 微信小程序教学第二章(含视频):小程序中级实战教程之预备篇 - 封装网络请求及 mock 数据
- 微信小程序教学第二章(含视频):小程序中级实战教程之预备篇 - 提取util公用方法 |基于最新版1.0开发者工具
- 微信小程序教学第三章第三节(含视频):小程序中级实战教程:视图与数据关联
- 微信小程序教学第三章第四节(含视频):小程序中级实战教程:下拉更新、分享、阅读标识
- 微信小程序教学第二章:小程序中级实战教程之预备篇 - 项目结构设计 |基于最新版1.0开发者工具
- 微信小程序开发实战视频教程发布
- 微信小程序开发实战视频教程
- 最新微信小程序(应用号)视频教程,实战教程