美文网首页
“真实世界”全栈开发-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