情诗网 >情感文章 > 正文

WeChat 文章详情页

来源:情诗网    2021-03-27    分类:情感文章

Unsplash

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

授权许可
0 系列文章目录

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

1 跳转文章详情页面

新建文章详情页,在 app.jsonpage 数组下新增页面路径 ``,保存之后,开发工具会自动生成 post-detail 详情页,在 post.wxml 中增加 view 容器包裹 template 模板,并注册跳转文章详情页事件,这里没有在 templateblock 标签上注册事件,是因为它们在编译之后“消失”了

<!--pages/post/post.wxml-->
<block wx:for="{{postList}}" wx:for-index="idx" wx:for-item="item">
  <view catchtap="onTapToDetail" data-post-id="{{item.postId}}">
    <template is="postItemTpl" data="{{...item}}" />
  </view>
</block>

我们在 post.js 文件中添加 onTapToDetail 事件,通过传入的 event 事件对象,获取到传入的 postId,其中 currentTarget 代表事件绑定的当前组件,而 dataset 对象里包含当前组件中所有属性名以 data- 开头的自定义属性值

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

Page({
  ...
  onTapToDetail(event) {
    const postId = event.currentTarget.dataset.postId
    console.log(postId)
    wx.navigateTo({
      url: `post-detail/post-detail?id=${postId}`
    })
  }
})

post-detail 页面中获取 postId

// pages/post/post-detail/post-detail.js
Page({
  data: {},
  onLoad: function (options) {
    let postId = options.id
  }
})
运行效果
2 跳转文章详情页面

现在我们主要的代码编辑工作集中在 post-detail 这个页面上,但每当保存刷新小程序后,项目都将从欢迎页面启动,我们不得不依次点击启动页面、文章列表,才能进入到文章详情页面以浏览文章详情的效果,这样非常不方便我们调试页面

官方提供了一个【自定义编译】功能,可用于定义小程序的启动页面,点击【普通编译】,随后在弹出的菜单中选择【添加编译模式】,将启动页面设置为 pages/post/post-detail/post-detail,启动参数可设为 id=4,若是有多个参数,可使用 & 进行连接

我们在文章详情页中拿到了 postId,接下来需要根据这个 postId 去缓存数据库中读取文章详细数据,并将数据用于构建文章详情页,在 DBPost.js 文件中修改 constructor 构造函数,增加一个构造参数 postId,并将其保存到 this 变量中,随后增加 getPostItemById 方法,用于获取指定 id 的文章数据

// db/DBPost.js
class DBPost {
  constructor(postId) {
    this.storageKeyName = 'postList'
    this.postId = postId
  }
  ...
  // 获取指定id的文章数据
  getPostItemById() {
    let postsData = this.getAllPostData()
    const len = postsData.length
    for(let i = 0; i < len; i++) {
      if(postsData[i].postId == this.postId) {
        return {
          // 当前文章在缓存数据库数组中的序号
          index: i,
          data: postsData[i]
        }
      }
    }
  }
}

随后我们在 post-detail.js 中获取指定 id 的文章数据,并使用 this.setData 绑定该数据

// pages/post/post-detail/post-detail.js
import { DBPost } from "../../../db/DBPost"
Page({
  data: {},
  onLoad: function (options) {
    let postId = options.id
    this.dbPost = new DBPost(postId)
    this.postData = this.dbPost.getPostItemById().data
    this.setData({
      post: this.postData
    })
  }
})
3 编写文章详情页面
<!--pages/post/post-detail/post-detail.wxml-->
<view class="container">
  <image class="head-image" src="{{post.postImg}}"/>
  <text class="title">{{post.title}}</text>
  <view class="author-date">
    <view class="author-box">
      <image class="avatar" src="{{post.avatar}}" />
      <text class="author">{{post.author}}</text>
    </view>
    <text class="date">{{post.dateTime}}</text>
  </view>
  <text class="detail">{{post.detail}}</text>
</view>
/* pages/post/post-detail/post-detail.wxss */
.container {display:flex;flex-direction:column;}
.head-image {width:750rpx;height:460rpx;}
.title {font-size:20px;margin:30rpx;letter-spacing:2px;color:#4b556c;}
.author-date {display:flex;flex-direction:row;margin-top:15rpx;margin-left:30rpx;align-items:center;justify-content:space-between;font-size:13px;}
.author-box {display:flex;flex-direction:row;align-items:center;}
.avatar {height:50rpx;width:50rpx;}
.author {font-weight:300;margin-left:20rpx;color:#666;}
.date {color:#919191;margin-right:38rpx;}
.detail {color:#666;margin:40rpx 22rpx 0;line-height:44rpx;letter-spacing:1px;font-size:14px;}

保存并刷新页面后,文章详情页将正确地显示出来,如下图所示

运行效果

post.json 文件中配置导航栏文字

{
  "navigationBarTextStyle": "white",
  "navigationBarTitleText": "标题"
}

post-detail.js 文件中动态设置导航栏文字为文章标题

Page({
  ...
  onReady: function() {
    wx.setNavigationBarTitle({
      title: this.postData.title
    })
  }
})
运行结果
4 收藏、点赞功能

由于我们的数据库只在本地,无法多次收藏同一篇文章,所以收藏数量永远只在初始数量的基础上 +1 或者 -1,分别对应点击收藏和取消收藏两种状态,但在真实的项目中,这个收藏数量却是要受到所有用户收藏、取消文章动作影响的,同样的情况也会出现在【文章点赞】功能中

接下来我们编写 3 个功能的功能按钮,每个按钮都绑定了对应的点击事件及当前文章的 id,并通过条件渲染 wx:ifwx:else 来控制图片的更换

<!--pages/post/post-detail/post-detail.wxml-->
<view class="container">
  ...
</view>
<view class="tool">
  <view class="tool-item" catchtap="onUpTap" data-post-id="{{post.postId}}">
     <image animation="{{animationUp}}" wx:if="{{post.upStatus}}" src="/images/icon/wx_app_liked.png" />
     <image animation="{{animationUp}}" wx:else src="/images/icon/wx_app_like.png" />
    <text>{{post.upNum}}</text>
  </view>
  <view class="tool-item comment" catchtap="onCommentTap" data-post-id="{{post.postId}}">
    <image src="/images/icon/wx_app_message.png"></image>
    <text>{{post.commentNum}}</text>
  </view>
  <view class="tool-item" catchtap="onCollectionTap" data-post-id="{{post.postId}}">
    <image wx:if="{{post.collectionStatus}}" src="/images/icon/wx_app_collected.png" />
    <image wx:else src="/images/icon/wx_app_collect.png" />
    <text>{{post.collectionNum}}</text>
  </view>
</view>
/* pages/post/post-detail/post-detail.wxss */
.tool {height:64rpx;margin:20rpx 28rpx 20rpx 0;display:flex;justify-content:center;}
.tool-item {align-items:center;margin-right:30rpx;display:flex;}
.tool-item:last-child {margin-right:0rpx;}
.tool-item image {height:30rpx;width:30rpx;margin-right:10rpx;}
.comment image {transform:scale(.85);}

接着我们在 DBPost.js 文件中添加 updatePostData 方法,用来更新本地的点赞、评论信息、收藏和阅读量

//收藏
collect() {
  return this.updatePostData("collect")
}

//点赞
up() {
  let data = this.updatePostData("up")
  return data
}

//更新本地的点赞、评论信息、收藏、阅读量
updatePostData(category, newComment) {
  let itemData = this.getPostItemById(),
    postData = itemData.data,
    allPostData = this.getAllPostData()
  switch (category) {
    case "collect":
      //处理收藏
      if (!postData.collectionStatus) {
        //如果当前状态是未收藏
        postData.collectionNum++
        postData.collectionStatus = true
      } else {
        // 如果当前状态是收藏
        postData.collectionNum--
        postData.collectionStatus = false
      }
      break
    case "up":
      if (!postData.upStatus) {
        postData.upNum++
        postData.upStatus = true
      } else {
        postData.upNum--
        postData.upStatus = false
      }
      break
    case "comment":
      postData.comments.push(newComment)
      postData.commentNum++
      break
    case "reading":
      postData.readingNum++
      break
    default:
      break
  }
  // 更新缓存数据库
  allPostData[itemData.index] = postData
  this.execSetStorageSync(allPostData)
  return postData
}

接着我们编写收藏文章的 onCollectionTap 事件函数,以及点赞操作的 onUpTap 事件函数,并通过 wx.showToast 进行友好的反馈提示交互

// pages/post/post-detail/post-detail.js
onCollectionTap: function (event) {
  let newData = this.dbPost.collect();
  // 重新绑定数据。注意,不要将整个newData全部作为setData的参数,
  // 应当有选择的更新部分数据
  this.setData({
    'post.collectionStatus': newData.collectionStatus,
    'post.collectionNum': newData.collectionNum
  })
  // 交互反馈
  wx.showToast({
    title: newData.collectionStatus ? "收藏成功" : "取消成功",
    duration: 1000,
    icon: "success",
    mask: true
  })
},

onUpTap: function (event) {
  let newData = this.dbPost.up();
  this.setData({
    'post.upStatus': newData.upStatus,
    'post.upNum': newData.upNum
  })
}
运行效果

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

End of File

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

热门文章