§ 頁面邏輯處理
本文配套視頻地址:
v.qq.com/x/page/n055…
開始前請把 ch3-2
分支中的 code/
目錄導(dǎo)入微信開發(fā)工具
修改 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)
數(shù)據(jù)綁定
我們首先挖出和渲染相關(guān)的數(shù)據(jù),并添加在 handler
對象的 data
字段中(Model 層)
修改 index.js
中的 handler
對象:
// 此處省略部分代碼 let handler = { data: { page: 1, //當(dāng)前加載第幾頁的數(shù)據(jù) days: 3, pageSize: 4, totalSize: 0, hasMore: true,// 用來判斷下拉加載更多內(nèi)容操作 articleList: [], // 存放文章列表數(shù)據(jù),與視圖相關(guān)聯(lián) defaultImg: config.defaultImg }, }
注意:后續(xù)添加的代碼都是放在 handler
對象中,它會傳遞到 Page
函數(shù)中用來初始化頁面組件
獲取數(shù)據(jù)
然后要做的就是獲取列表的數(shù)據(jù),初始化數(shù)據(jù)的工作我們一般放在生命周期的 onLoad()
里:
let handler = { onLoad (options) { this.requestArticle() }, /* * 獲取文章列表數(shù)據(jù) */ 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 ) }); } }
數(shù)據(jù)加載完成之后,我們需要對接口返回的數(shù)據(jù)進行業(yè)務(wù)方面的容錯處理
修改 requestArticle
函數(shù):
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 => { // 數(shù)據(jù)正常返回 if (res && res.status === 0 && res.data && res.data.length) { // 正常數(shù)據(jù) do something console.log(res) } /* * 如果加載先進頁就沒有數(shù)據(jù),說明數(shù)據(jù)存在異常情況 * 處理方式:彈出異常提示信息(默認提示信息)并設(shè)置下拉加載功能不可用 */ else if (this.data.page === 1 && res.data && res.data.length === 0) { util.alert(); this.setData({ hasMore: false }); } /* * 如果非先進頁沒有數(shù)據(jù),那說明沒有數(shù)據(jù)了,停用下拉加載功能即可 */ else if (this.data.page !== 1 && res.data && res.data.length === 0) { this.setData({ hasMore: false }); } /* * 返回異常錯誤 * 展示后端返回的錯誤信息,并設(shè)置下拉加載功能不可用 */ else { util.alert('提示', res); this.setData({ hasMore: false }); return null; } }) } }
上面我們把 wx.request
重新包裝成了 Promise
的形式,其實我們是請求的 mock 數(shù)據(jù)。但是接口請求到的數(shù)據(jù)絕大部分情況下都不會直接適用于 UI
展示,所以我們需要做一層數(shù)據(jù)轉(zhuǎn)換,把接口數(shù)據(jù)轉(zhuǎn)換成視圖數(shù)據(jù)。
格式化數(shù)據(jù)
先看下后端返回的數(shù)據(jù)結(jié)構(gòu)

我們需要做兩件事情
-
遍歷
data
數(shù)組,對返回的日期格式化,當(dāng)天的顯示今天
,如果是今年的文章,顯示月日格式08-21
;如果是往年的文章,顯示標(biāo)準(zhǔn)的年月日格式2015-06-12
。 -
遍歷
articles
數(shù)組,判斷此篇文章的contentId
是否已經(jīng)在全局變量visitedArticles
中,如果存在,說明已經(jīng)訪問過。
修改 app.js
,增加全局變量 visitedArticles
globalData: { user: { name: '', avator: '' }, visitedArticles: '' }
修改 index.js
中的 requestArticle
函數(shù):
let handler = { // 此處省略部分代碼 requestArticle () { // 注意:修改此處代碼 if (res && res.status === 0 && res.data && res.data.length) { let articleData = res.data; //格式化原始數(shù)據(jù) let formatData = this.formatArticleData(articleData); console.log( formatData ) } } }
增加對列表數(shù)據(jù)格式化的代碼:
let handler = { // 此處省略部分代碼 /* * 格式化文章列表數(shù)據(jù) */ 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) => { // 判斷是否已經(jīng)訪問過 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; }, }
正常情況下,這個時候控制臺打印出來的數(shù)據(jù),是經(jīng)過格式化的標(biāo)準(zhǔn)數(shù)據(jù)了,下一步,我們需要把它添加到 data
中的 articleList
字段里面,這樣視圖才有了渲染的數(shù)據(jù)
修改 index.js
,增加 renderArticle
函數(shù)。由于每次請求的都是某一頁的數(shù)據(jù),所以在函數(shù)中,我們需要把每次請求過來的列表數(shù)據(jù)都 concat
(拼接)到 articleList
中:
let handler = { // 此處省略部分代碼 renderArticle (data) { if (data && data.length) { let newList = this.data.articleList.concat(data); this.setData({ articleList: newList }) } } }
在 requestArticle
函數(shù)中調(diào)用 renderArticle
:
let handler = { // 此處省略部分代碼 requestArticle () { // 注意:修改此處代碼 if (res && res.status === 0 && res.data && res.data.length) { let articleData = res.data; //格式化原始數(shù)據(jù) let formatData = this.formatArticleData(articleData); this.renderArticle( formatData ) } } }
最終結(jié)果
最終的 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, //當(dāng)前的頁數(shù) days: 3, pageSize: 4, totalSize: 0, hasMore: true,// 用來判斷下拉加載更多內(nèi)容操作 articleList: [], // 存放文章列表數(shù)據(jù) defaultImg: config.defaultImg }, onLoad(options) { this.requestArticle(); }, /* * 獲取文章列表數(shù)據(jù) */ 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 => { // 數(shù)據(jù)正常返回 if (res && res.status === 0 && res.data && res.data.length) { let articleData = res.data; //格式化原始數(shù)據(jù) let formatData = this.formatArticleData(articleData); this.renderArticle(formatData) } /* * 如果加載先進頁就沒有數(shù)據(jù),說明數(shù)據(jù)存在異常情況 * 處理方式:彈出異常提示信息(默認提示信息)并設(shè)置下拉加載功能不可用 */ else if (this.data.page === 1 && res.data && res.data.length === 0) { util.alert(); this.setData({ hasMore: false }); } /* * 如果非先進頁沒有數(shù)據(jù),那說明沒有數(shù)據(jù)了,停用下拉加載功能即可 */ else if (this.data.page !== 1 && res.data && res.data.length === 0) { this.setData({ hasMore: false }); } /* * 返回異常錯誤 * 展示后端返回的錯誤信息,并設(shè)置下拉加載功能不可用 */ else { util.alert('提示', res); this.setData({ hasMore: false }); return null; } }) }, /* * 格式化文章列表數(shù)據(jù) */ 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) => { // 判斷是否已經(jīng)訪問過 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)
下一篇中,我們將會把數(shù)據(jù)與視圖層結(jié)合在一起,動態(tài)的展示視圖層
iKcamp官網(wǎng):www.ikcamp.com
訪問官網(wǎng)更快閱讀全部免費分享課程:《iKcamp出品|全網(wǎng)較新|微信小程序|基于較新版1.0開發(fā)者工具之初中級培訓(xùn)教程分享》。
包含:文章、視頻、源代碼

iKcamp原創(chuàng)新書《移動Web前端高效開發(fā)實戰(zhàn)》已在亞馬遜、京東、當(dāng)當(dāng)開售。
iKcamp較新活動

報名地址: www.huodongxing.com/event/54099…
與 “天天練口語”
小程序總榜排名第四、教育類排名先進的研發(fā)團隊,面對面溝通交流。