微信小程序教學第三章(含視頻):小程序中級實戰教程:列表篇-頁面邏輯處理

列表篇-頁面邏輯處理

本文配套視頻地址: v.qq.com/x/page/z055…javascript


開始前請把 ch3-2 分支中的 code/ 目錄導入微信開發工具html


修改 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 函數中用來初始化頁面組件

java

獲取數據

而後要作的就是獲取列表的數據,初始化數據的工做咱們通常放在生命週期的 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官網:www.ikcamp.com

訪問官網更快閱讀所有免費分享課程:《iKcamp出品|全網最新|微信小程序|基於最新版1.0開發者工具之初中級培訓教程分享》。 包含:文章、視頻、源代碼

iKcamp原創新書《移動Web前端高效開發實戰》已在亞馬遜、京東、噹噹開售。

iKcamp最新活動

報名地址:www.huodongxing.com/event/54099…

「每天練口語」小程序總榜排名第4、教育類排名第一的研發團隊,面對面溝通交流。


2019年,iKcamp原創新書《Koa與Node.js開發實戰》已在京東、天貓、亞馬遜、噹噹開售啦!

相關文章
相關標籤/搜索