让前端飞Web前端之路

WeChat 文章评论页(一)

2020-03-05  本文已影响0人  Nian糕
Unsplash

本次的系列博文的知识点讲解和代码,主要是来自于 七月老师 的书籍《微信小程序开发:入门与实践》,由个人总结并编写,关于更多微信小程序开发中的各项技能,以及常见问题的解决方案,还请大家购买书籍进行学习实践,该系列博文的发布已得到七月老师的授权许可

授权许可

0 系列文章目录

01 WeChat 从一个简单的“Welcome”页面来开启小程序之旅吧
02 WeChat 文章列表页面(一)
03 WeChat 文章列表页面(二)
04 WeChat 模块、模板与缓存
05 WeChat 文章详情页
06 WeChat 文章评论页(一)

1 获取文章评论数据

通过 app.json 中的 pages 数组注册 post-comment 页面,该页面作为 post-detail 的子页面,用于文章评论,在 post.js 文件中添加 onCommentTap 方法进行页面跳转

// pages/post/post-detail/post-detail.js
onCommentTap: function (event) {
  const id = event.currentTarget.dataset.postId;
  wx.navigateTo({
    url: `../post-comment/post-comment?id=${id}`
  })
}

构建文章评论页的思路分为两部分,一是加载并显示当前文章已存在的评论,二是实现添加新评论的功能,我们在 postId 为 2 的《从童年呼啸而过的火车》文章中模拟了 4 条评论数据,即 comments 数组,将其读取并绑定到框架中

// pages/post/post-comment/post-comment.js
import { DBPost } from '../../../db/DBPost.js'

Page({
  data: {},
  onLoad: function(options) {
    let postId = options.id
    this.dbPost = new DBPost(postId)
    let comments = this.dbPost.getCommentData()
    // 绑定评论数据
    this.setData({
      comments: comments
    })
  }
})
// db/DBPost.js
let util = require('../util/util.js')

class DBPost {
  ...
  // 获取文章的评论数据
  getCommentData() {
    let itemData = this.getPostItemById().data
    // 按时间降序排列评论
    itemData.comments.sort(this.compareWithTime)
    let len = itemData.comments.length,
        comment
    for(let i = 0; i < len; i++) {
      // 将comment中的时间戳转换成可阅读格式
      comment = itemData.comments[i]
      comment.create_time = util.getDiffTime(comment.create_time, true)
    }
    return itemData.comments
  }

  compareWithTime(value1, value2) {
    let flag = parseFloat(value1.create_time) - parseFloat(value2.create_time);
    if (flag < 0) {
      return 1;
    } else if (flag > 0) {
      return -1
    } else {
      return 0;
    }
  }
}
// util/util.js
/*
 *根据客户端的时间信息得到发表评论的时间格式
 *多少分钟前,多少小时前,然后是昨天,然后再是月日
 * Para :
 * recordTime - {float} 时间戳
 * yearsFlag -{bool} 是否要年份
 */
function getDiffTime(recordTime, yearsFlag) {
  if (recordTime) {
    recordTime = new Date(parseFloat(recordTime) * 1000)
    let minute = 1000 * 60,
        hour   = minute * 60,
        day    = hour * 24,
        now    = new Date(),
        diff   = now - recordTime,
        result = ""
    if (diff < 0) {
      return result;
    }
    let weekR = diff / (7 * day),
        dayC  = diff / day,
        hourC = diff / hour,
        minC  = diff / minute
    if (weekR >= 1) {
      let formate = "MM-dd hh:mm"
      if (yearsFlag) {
        formate = "yyyy-MM-dd hh:mm"
      }
      return recordTime.format(formate)
    } else if (
      dayC == 1 ||
      (hourC < 24 && recordTime.getDate() != now.getDate())
    ) {
      result = "昨天" + recordTime.format("hh:mm");
      return result
    } else if (dayC > 1) {
      let formate = "MM-dd hh:mm"
      if (yearsFlag) {
        formate = "yyyy-MM-dd hh:mm"
      }
      return recordTime.format(formate)
    } else if (hourC >= 1) {
      result = parseInt(hourC) + "小时前"
      return result
    } else if (minC >= 1) {
      result = parseInt(minC) + "分钟前"
      return result
    } else {
      result = "刚刚"
      return result
    }
  }
  return ""
}

/*
 *拓展Date方法。得到格式化的日期形式
 *date.format('yyyy-MM-dd'),date.format('yyyy/MM/dd'),date.format('yyyy.MM.dd')
 *date.format('dd.MM.yy'), date.format('yyyy.dd.MM'), date.format('yyyy-MM-dd HH:mm')
 *使用方法 如下:
 *                       let date = new Date();
 *                       let todayFormat = date.format('yyyy-MM-dd'); //结果为2015-2-3
 *Parameters:
 *format - {string} 目标格式 类似('yyyy-MM-dd')
 *Returns - {string} 格式化后的日期 2015-2-3
 *
 */
(function initTimeFormat() {
  Date.prototype.format = function(format) {
    let o = {
      "M+": this.getMonth() + 1, //month
      "d+": this.getDate(), //day
      "h+": this.getHours(), //hour
      "m+": this.getMinutes(), //minute
      "s+": this.getSeconds(), //second
      "q+": Math.floor((this.getMonth() + 3) / 3), //quarter
      S: this.getMilliseconds() //millisecond
    }
    if (/(y+)/.test(format))
      format = format.replace(
        RegExp.$1,
        (this.getFullYear() + "").substr(4 - RegExp.$1.length)
      )
    for (let k in o)
      if (new RegExp("(" + k + ")").test(format))
        format = format.replace(
          RegExp.$1,
          RegExp.$1.length == 1
            ? o[k]
            : ("00" + o[k]).substr(("" + o[k]).length)
        )
    return format
  }
})()
module.exports = {
  getDiffTime: getDiffTime
}

compareWithTime 方法用于将评论按照时间降序排列,保证最新的评论在最上方,util.getDiffTime 方法用于将评论的时间戳转化为“多少分钟前,多少小时前,昨天,月日”等格式,其中 util.getDiffTime 为公共方法,我们新建了一个 util 文件夹,将所有的公共方法都放置到该文件夹下

运行结果

评论支持文本、图片和录音 3 种类型,在 content 属性下,img 数组是评论中的图片,txt 是评论中的文本,audio 是评论中的音频,其中,图片类型评论最多只能包含 3 张图片,音频类型评论只能包含一条音频,一条评论可以包含文字和图片,音频类型评论不能包含文字和图片

2 显示文章评论数据

在每张 image 图片上注册 catchtap="previewImg" 事件,用来响应点击图片的操作,wx:for-index="imgIdx" 用以定义图片序号,自定义属性 data-comment-idx="{{idx}}" 用来绑定当前评论在评论数组中的序号,自定义属性 data-img-idx="{{imgIdx}}" 用来绑定图片在图片数组中的序号

<!--pages/post/post-comment/post-comment.wxml-->
<view class="comment-detail-box">
  <view class="comment-main-box">
    <view class="comment-title">评论………(共{{comments.length}}条)</view>
    <block wx:for="{{comments}}" wx:for-item="item" wx:for-index="idx">
      <view class="comment-item">
        <view class="comment-item-header">
          <view class="left-img">
            <image src="{{item.avatar}}"></image>
          </view>
          <view class="right-user">
            <text class="user-name">{{item.username}}</text>
          </view>
        </view>
        <view class="comment-body">
          <view class="comment-txt" wx:if="{{item.content.txt}}">
            <text>{{item.content.txt}}</text>
          </view>
          <view class="comment-voice" wx:if="{{item.content.audio && item.content.audio.url}}">
            <view data-url="{{item.content.audio.url}}" class="comment-voice-item" catchtap="playAudio">
              <image src="/images/icon/wx_app_voice.png" class="voice-play"></image>
              <text>{{item.content.audio.timeLen}}''</text>
            </view>
          </view>
          <view class="comment-img" wx:if="{{item.content.img.length!=0}}">
            <block wx:for="{{item.content.img}}" wx:for-item="img" wx:for-index="imgIdx">
              <image src="{{img}}" mode="aspectFill" catchtap="previewImg" data-comment-idx="{{idx}}" data-img-idx="{{imgIdx}}"></image>
            </block>
          </view>
        </view>
        <view class="comment-time">{{item.create_time}}</view>
      </view>
    </block>
  </view>
</view>
/* pages/post/post-comment/post-comment.wxss */
.comment-detail-box {position:absolute;top:0;left:0;bottom:0;right:0;overflow-y:hidden;}
.comment-main-box {position:absolute;top:0;left:0;bottom:100rpx;right:0;overflow-y:auto;-webkit-overflow-scrolling:touch;}
.comment-item {margin:20rpx 0 20rpx 24rpx;padding:24rpx 24rpx 24rpx 0;border-bottom:1rpx solid #f2e7e1;}
.comment-item:last-child {border-bottom:none;}
.comment-title {height:60rpx;line-height:60rpx;font-size:28rpx;color:#212121;border-bottom:1px solid #ccc;margin-left:24rpx;padding:8rpx 0;font-family:Microsoft YaHei;}
.comment-item-header {display:flex;flex-direction:row;align-items:center;}
.comment-item-header .left-img image {height:80rpx;width:80rpx;}
.comment-item-header .right-user {margin-left:30rpx;line-height:80rpx;}
.comment-item-header .right-user text {font-size:26rpx;color:#212121;}
.comment-body {font-size:26rpx;line-height:26rpx;color:#666;padding:10rpx 0;}
.comment-txt text {line-height:50rpx;}
.comment-img {margin:10rpx 0;}
.comment-img image {max-width:32%;margin-right:10rpx;height:220rpx;width:220rpx;}
.comment-voice-item {display:flex;flex-direction:row;align-items:center;width:200rpx;height:64rpx;border:1px solid #ccc;background-color:#fff;border-radius:6rpx;}
.comment-voice-item .voice-play {height:64rpx;width:64rpx;}
.comment-voice-item text {margin-left:60rpx;color:#212121;font-size:22rpx;}
.comment-time {margin-top:10rpx;color:#ccc;font-size:24rpx;}

// pages/post/post-comment/post-comment.js
Page({
  ...
  //预览图片
  previewImg: function (event) {
    //获取评论序号
    let commentIdx = event.currentTarget.dataset.commentIdx,
        //获取图片在图片数组中的序号
        imgIdx = event.currentTarget.dataset.imgIdx,
        //获取评论的全部图片
        imgs = this.data.comments[commentIdx].content.img;
    wx.previewImage({
        current: imgs[imgIdx], // 当前显示图片的http链接
        urls: imgs // 需要预览的图片http链接列表
    })
  }
})
运行结果

该章节的内容到这里就全部结束了,源码我已经发到了 GitHub WeChat_06 上了,有需要的同学可自行下载

End of File

行文过程中出现错误或不妥之处在所难免,希望大家能够给予指正,以免误导更多人,最后,如果你觉得我的文章写的还不错,希望能够点一下喜欢关注,为了我能早日成为简书优秀作者献上一发助攻吧,谢谢!^ ^

上一篇下一篇

猜你喜欢

热点阅读