微信小程序教学第三章(含视频):小程序中级实战教程:列表-页面逻辑处理

§ 页面逻辑处理

本文配套视频地址:
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

“天天练口语”小程序总榜排名第四、教育类排名第一的研发团队,面对面沟通交流。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
老规矩,先看本节效果图我们实现这个支付功能完全是借助小程序云开发实现的,不用搭建自己的服务器,不用买域名,不用备案域名,不用支持https。只需要一个简单的云函数,就可以轻松的实现微信小程序支付功能。核心代码就下面这些一,创建一个云开发小程序关于如何创建云开发小程序,这里我就不再做具体讲解。不知道怎么创建云开发小程序的同学,可以去翻看我之前的文章,或者看下我录制的视频:https://edu.csdn.net/course/play/9604/204528创建云开发小程序有几点注意的1,一定不要忘记在app.js里初始化云开发环境。2,创建完云函数后,一定要记得上传二, 创建支付的云函数1,创建云函数pay三,引入三方依赖tenpay我们这里引入三方依赖的目的,是创建我们支付时需要的一些参数。我们安装依赖是使用里npm 而npm必须安装node,关于如何安装node,我这里不做讲解,百度一下,网上一大堆。1,首先右键pay,然后选择在终端中打开2,我们使用npm来安装这个依赖。在命令行里执行 npm i tenpay安装完成后,我们的pay云函数会多出一个package.json 文件到这里我们的tenpay依赖就安装好了。四,编写云函数pay完整代码如下//云开发实现支付 const cloud = require('wx-server-sdk')cloud.init() //1,引入支付的三方依赖 const tenpay = require('tenpay'); //2,配置支付信息 const config = ;exports.main = async(event, context) => 一定要注意把appid,mchid,partnerKey换成你自己的。到这里我们获取小程序支付所需参数的云函数代码就编写完成了。不要忘记上传这个云函数。出现下图就代表上传成功五,写一个简单的页面,用来提交订单,调用pay云函数。这个页面很简单,1,自己随便编写一个订单号(这个订单号要大于6位)2,自己随便填写一个订单价(单位是分)3,点击按钮,调用pay云函数。获取支付所需参数。下图是官方支付api所需要的一些必须参数。下图是我们调用pay云函数获取的参数,和上图所需要的是不是一样。六,调用wx.requestPayment实现支付下图是官方的示例代码这里不在做具体讲解了,完整的可以看视频。实现效果1,调起支付键盘2,支付完成3,log日志,可以看出不同支付状态的回调上图是支付成功的回调,我们可以在支付成功回调时,改变订单支付状态。下图是支付失败的回调,下图是支付完成的状态。到这里我们就轻松的实现了微信小程序的支付功能了。是不是很简单啊,完整的讲解可以看视频

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值