美文网首页让前端飞Web前端之路
WeChat 文章评论页(一)

WeChat 文章评论页(一)

作者: Nian糕 | 来源:发表于2020-03-05 19:19 被阅读0次
    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

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

    相关文章

      网友评论

        本文标题:WeChat 文章评论页(一)

        本文链接:https://www.haomeiwen.com/subject/rbktrhtx.html