美文网首页
“真实世界”全栈开发-3.9-为博文点赞

“真实世界”全栈开发-3.9-为博文点赞

作者: 桥头堡2015 | 来源:发表于2018-02-10 17:27 被阅读16次

为博文点赞的功能支持两种信息的查询:某篇博文所得的赞的总数目,以及某个用户点过赞的所有博文的列表。为此,我们需要对用户和博文的模型做一些小改动。

修改模型

我们可以在用户模型里存储所有其点过赞的博文的ID,也可以反过来在博文模型里存储所有为其点过赞的用户的ID。由于我们只需为博文显示赞的个数,所以前一种方式显然更合适。

为用户模型添加其点过赞的博文的ID数组

打开models/User.js,在UserSchema的定义里加入一行代码:

hash: String,
// +++
favorites: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Article' }],
// +++
salt: String

按说用户点过赞的博文ID最好存储在一个集合里(比如ES6的Set),然而Mongoose支持的模式类型里只有数组没有集合,所以在后面加入博文ID时,需要查重。

添加博文到点赞列表的方法

仍然在models/User.js里,加入如下代码:

UserSchema.methods.favorite = function (id) {
  if (this.favorites.indexOf(id) === -1)
    this.favorites.push(id);

  return this.save();
};

取消点赞的方法

继续加入下面的代码:

UserSchema.methods.unfavorite = function (id) {
  this.favorites.remove( id );
  return this.save();
};

检查是否为某篇博文点过赞的方法

UserSchema.methods.isFavorite = function (id) {
  return this.favorites.some(fid => fid.toString() === id.toString());
};

前端为登录用户显示某篇博文时,后端会用到上面这个方法来检查该用户是否为该博文点过赞,并且得把这个信息同博文JSON对象一起返回给前端。

更新博文JSON对象

打开models/Article.js,修改uArticleScheme.methods.toJSONFor,加入一行代码:

ArticleSchema.methods.toJSONFor = function (user) {
  return {
    // ...
    // +++
    favorited: user ? user.isFavorite(this._id) : false,
    // +++
    favoritesCount: this.favoritesCount,
    author: this.author.toProfileJSONFor(user)
  };
};

统计点赞数的方法

接下来我们需要一个方法来统计博文获得的点赞数。

我们利用Mongoose的查询语句来做统计。

首先往models/Article.js里导入User模型:

const User = mongoose.model('User');

然后添加如下的代码:

ArticleSchema.methods.updateFavoritesCount = function () {
  return User.count({favorites: {$in: [this._id]}})
    .then(count => {
      this.favoritesCount = count;
      return this.save()
    });
};

点赞功能所需的所有模型上的改动就全部完成了。

创建API端点

接下来我们用改动好的模型来所需的API端点。

为博文点赞的端点

POST /api/articles/:slug/favorite,需要身份验证,不需要请求体,返回同一博文的JSON对象。

打开routes/api/articles.js,加入如下代码:

// 点赞
router.post('/:slug/favorite', auth.required, function(req, res, next) {
  res.locals.user.favorite(res.locals.article._id)
    .then(() => res.locals.article.updateFavoritesCount())
    .then(article => res.json({article: article.toJSONFor(res.locals.user)}))
    .catch(next);
}, respondArticle);

取消点赞的端点

与点赞的端点十分相似,不过所用的HTTP方法为DELETE

完整的端点为DELETE /api/articles/:slug/favorite,需要身份验证,不需要请求体,也是返回该博文的JSON对象。

// 取消点赞
router.delete('/:slug/favorite', auth.required, loadCurrentUser, (req, res, next) => {
  res.locals.user.unfavorite(res.locals.article._id)
    .then(() => res.locals.article.updateFavoritesCount())
    .then(() => next())
    .catch(next);
}, respondArticle);

以上就是为博文点赞功能的实现。

相关文章

网友评论

      本文标题:“真实世界”全栈开发-3.9-为博文点赞

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