微信小程序基于云数据库实现点赞功能
微信小程序基于云数据库实现点赞功能
-
首先你要开通云开发,然后点击数据库创建集合(这里我的集合是‘Books’),然后在集合里面添加数据,注意将集合对应的权限改为“自定义安全规则”
-
将安全规则自定义为“所有用户可读写”
-
思路如下:
- 利用云函数获取用户的openid
- 从数据库获取需要的like,like_num,like_people(放对应书籍id的点赞用户的openid)等数据,放入新建newList的数组中
- 在newList的like_people这个二维数组中遍历当前用户openid是否出现过,出现过则把该用户点赞过的书籍id放入新建iszan数组中
- 寻找iszan数组和newList数组中相同的id(我用的方法时间复杂度都是O(n²),有更好方法欢迎指导),有相同的则“点亮红心”
- 点赞事件:只需一个判断条件——①iszan数组中是否包含该书籍id或者②该书籍的like_people数组是否包含该用户openid,如果是的话就“取消点赞”,否则“点赞”
- 和后台交互,后台数据要同步,使用update
代码:
wxml
<block wx:for='{{newsList}}' wx:key="index">
<view class='item-zan' bindtap='thumbsup' data-id='{{item._id}}'>
<image src='/images/like.png' style="width:60rpx;height:60rpx" wx:if="{{!item.like}}"></image><!--未点赞-->
<image src='/images/like_active.png' style="width:60rpx;height:60rpx" wx:else></image><!--点赞-->
<view style="margin-left:20rpx">{{item.like_num}}</view>
</view>
</block>
通过thumbsup事件完成点赞,把其中的like由false改为true(取消点赞则是相反)来显示
js
const db = wx.cloud.database()
const _ = db.command
const booksCollection = db.collection('Books')
Page({
data: {
newsList: [], //列表数据
iszan: [], //点过赞的id集合
like_people: [], //每个列表数据的点赞的用户集合
openid: ''
},
//页面加载初始化列表数据
onLoad: function () {
let that = this;
wx.cloud.callFunction({
name: 'getOpenid',
complete: res => { // 获取用户openid
console.log('云函数获取到的openid: ', res.result.openid)
that.setData({
openid: res.result.openid
})
booksCollection.field({ //发送请求获取列表数据
_id: true,
like: true,
like_num: true,
like_people: true
}).get({
success: res => {
that.setData({
newsList: res.data
})
var iszan = that.data.iszan;
for (var i = 0; i < res.data.length; i++) { //数据获取成功后,进行遍历,拿到所有已经点过赞的书籍id
for (let j = 0; j < res.data[i].like_people.length; j++) {
if (res.data[i].like_people[j] == that.data.openid) {
iszan.push(res.data[i]._id) //根据改用户的数据找到已经点赞的,把书籍id放入新建数组中
}
}
}
for (let i = 0; i < res.data.length; i++) {
res.data[i].like = false
for (let j = 0; j < iszan.length; j++) { //利用新建的iszan数组与list数组的id查找相同的书籍id
if (res.data[i]._id == iszan[j]) { //双重循环遍历,有相同的id则点亮红心
res.data[i].like = true
}
}
}
console.log(res.data)
that.setData({
iszan: this.data.iszan,
newsList: res.data
})
wx.setStorageSync('zan', iszan);
}
})
}
})
},
// 点赞函数 获取对应id
thumbsup: function (e) {
var shareid = e.currentTarget.dataset.id;
this.zan(shareid);
},
//点赞处理函数
zan: function (item_id) {
var that = this;
var cookie_id = wx.getStorageSync('zan') || []; //获取全部点赞的id
var openid = that.data.openid
console.log(openid)
for (var i = 0; i < that.data.newsList.length; i++) {
if (that.data.newsList[i]._id == item_id) { //数据列表中找到对应的id
var num = that.data.newsList[i].like_num; //当前点赞数
if (cookie_id.includes(item_id) ) { //已经点过赞了,取消点赞
for (var j in cookie_id) {
if (cookie_id[j] == item_id) {
cookie_id.splice(j, 1); //删除取消点赞的id
}
}
--num; //点赞数减1
that.setData({
[`newsList[${i}].like_num`]: num, //es6模板语法,常规写法报错
[`newsList[${i}.].like`]: false //我的数据中like为'false'是未点赞
})
wx.setStorageSync('zan', cookie_id);
wx.showToast({
title: "取消点赞",
icon: 'none'
})
this.data.newsList[i].like_people.pop(openid)
} else { //点赞操作
++num; //点赞数加1
that.setData({
[`newsList[${i}].like_num`]: num,
[`newsList[${i}.].like`]: true
})
cookie_id.unshift(item_id); //新增赞的id
wx.setStorageSync('zan', cookie_id);
wx.showToast({
title: "点赞成功",
icon: 'none'
})
this.data.newsList[i].like_people.push(openid)
}
//和后台交互,后台数据要同步
booksCollection.doc(item_id).update({
data: {
like: this.data.newsList[i].like,
like_num: num,
like_people: this.data.newsList[i].like_people
},
success: res => {
console.log(res)
}
})
}
}
}
})
小Tips
- 使用云函数获取用户id借鉴于 微信小程序开通云开发并利用云函数获取Openid
- 如果项目是使用服务器的话就需要把wx.cloud.callFunction()接口换成wx.request()即可。如是使用自搭服务器请参考↓,本文点赞功能主体也是借鉴于此 微信小程序列表点赞功能
2022.04.27 更新
这是以前菜鸡的我写的,现在抛开这篇文章来看这个需求,最好的实现方式是:
- 每个用户维护一个数组A,数组A的元素是书籍列表中已点赞的书籍的索引(数组下标);
- 拉取书籍列表后,前端根据数组A来判断每本书籍该用户是否点赞过。
思维导图如下:
之前的代码我就不删掉了,按照这个新思路欢迎大家自行重构代码