实现仿掘金的评论功能

3,425 阅读8分钟

大家好,我是爱编程的Mark。这是我虎年创作的第一篇技术类文章,主要阐述一下我实现的仿掘金评论功能

如果你也像我一样开发了自己的个人博客,但是还没有实现一个合适的评论功能,还没有合适的思路;那么我建议你读一下这篇文章。或者你对目前使用的评论功能还不满意,也可以试着从我的思路中找到灵感。

首先,来看看我想设计的评论功能想实现什么目的?

创作意图


  1. 读者在评论前需要提供一些关键信息,才能发表评论

这么做的目的是对评论根据读者分门别类,避免产生大量的垃圾评论,同时也方便读者找到自己以往的评论。而且这些读者就是博客的用户,方便我对用户的管理。

同时,为了避免操作流程过于复杂,同时降低程序的难度,我不需要读者走注册登录的流程。因为,我设计评论功能的目的是为了和读者交流,而不是冲着获取用户的商业目的。这里先看看一个没有登录过的读者需要提供的登录信息的截图:

20220213162631.jpg

我需要读者提供个人的昵称邮箱个人网站。其中昵称用于标识读者的,邮箱是读者的唯一标识同时也是联系方式,个人网站被设置在头像上,方便交流。读者填写这些信息后程序会将数据写入数据库,同时写入localstorage,读者只需要在首次评论填写信息即可。

因为个人博客不是平台性质的。不需要收集读者的信息,只需要可以唯一标识读者和方便联系读者。所以我认为,这里不需要去验证读者信息。这一点和掘金不同。

同时,用户点击默认的头像时可以修改个人头像。

  1. 提供一个醒目的发表评论的入口

    这一点我是完全参考的掘金的UI设计思路开发的。

    掘金使用contenteditable属性把一个div变成可编辑的,获取divinnerText得到用户的输入。这个属性我在大学时期仿照着Facebook编写评论功能是第一次遇到,但当时我只会jquery,照着实现了仿Facebook的评论功能。但这次,我不需要这么做。

    我直接用element-plus的input组件代替即可,因为我不需要在评论中插入图片和emoji表情功能,这些功能不是必要的,还会增加我的工作量,权衡之下没有实现。

    上面我啰嗦一段话是想象读者传递一个观点:选择性地去实现主要功能,细枝末节的功能可以舍弃掉,避免工作量加大导致无法完成或者耗时太久。同时,作为前端工程师除非有UI设计的专业能力,尝试去仿照已有的UI可以节省很多时间。

    这是实现后的截图,和掘金的很相像:

20220213170830.jpg

  1. 实现评论列表功能

    这里是整个评论功能最负责也最核心的地方。

    我仍旧是舍弃了掘金的“热门评论”功能,因为我不清楚掘金是如何界定什么样的评论属于热门评论,同时依旧是为了减少工作量。 这里我来分析一下掘金的评论功能的几个关键点:

    1. 点赞评论与取消点赞;
    2. 一级评论;
    3. 二级评论;

    第一点很好理解,用户可以点赞评论取消点赞。那个用户在执行这两个操作时,必须要获取当前唯一的用户信息,不然就可以取消别人的点赞或者无限增加点赞。同时,由于已知用户信息,所以可以高亮当前用户已点赞的评论用于标识。

    第二点也很好理解,显示用户的评论内容,发表时间,提供点赞功能和评论功能的入口;

    第三点理解起来就比较复杂,因为用户可以对别人的评论做二级评论,那么自然也可以评论别人的二级评论。这个如果不加控制,就会有无限级的评论出现。无限级的评论UI展示起来会很不正常,那么就需要有一个限制,控制评论到几级就不再往下递归。

    我仍记得第一次遇到这种情况是仿制Facebook的评论功能,那时候的Facebook最多可以做到三级评论,而掘金是两级评论。三级甚至更多级别的评论,会在用户名后面添加回复的对象和回复的内容

    参考我任意截的一条评论:

20220213172612.jpg

同时考虑到,我个人博客的访问量也很少,评论不会很多,不要特别去做分页和加载更多评论的功能。仍旧节省了工作量,哈哈。

3. 评论工具条

掘金的文章左侧有一个工具条,实现了快捷的点赞、评论、收藏、分享等功能。个人认为,这里可以有一定的扩展性;但是由于时间原因,我没有去实现它。个人认为这个功能也是可有可无,但是扩展性很强,有时间我会去实现它。

比如,实现分享到微信、QQ、微博,或者提取当前用户的所有评论等等。

这是掘金的评论工具条的截图:

20220213173905.jpg

代码逻辑


首先我先贴出这个组件的前端代码地址:https://github.com/programmerMark/easy-blog/tree/master/src/components/comment(使用Vue3+element-plus)

然后是组件涉及到的后端表结构,访客表(visitor)、访客评论表(visitor_comment)、访客点赞表(visitor_like)。下面是三张表的表结构设计:

visitor表

20220213175826.jpg

-- ----------------------------
-- Table structure for visitor
-- ----------------------------
DROP TABLE IF EXISTS `visitor`;
CREATE TABLE `visitor` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `nickname` varchar(50) NOT NULL COMMENT '昵称',
  `portrait` varchar(100) DEFAULT NULL COMMENT '游客头像图片地址',
  `email` varchar(50) DEFAULT NULL COMMENT '游客邮箱',
  `site` varchar(50) DEFAULT NULL COMMENT '游客网址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;

visitor_comment表

20220213180238.jpg

-- ----------------------------
-- Table structure for visitor_comment
-- ----------------------------
DROP TABLE IF EXISTS `visitor_comment`;
CREATE TABLE `visitor_comment` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `visitor_id` int unsigned NOT NULL COMMENT '发表评论的游客id',
  `talk_id` int unsigned DEFAULT NULL COMMENT '被评论的那条说说的id,可以为空',
  `article_id` int unsigned DEFAULT NULL COMMENT '被评论的那篇文章的id,可以为空',
  `novel_id` int unsigned DEFAULT NULL COMMENT '被评论的那本小说的那一章节的id,可以为空',
  `about_id` int unsigned DEFAULT NULL COMMENT '关于我的评论',
  `comment` text NOT NULL COMMENT '评论的内容',
  `be_comment_id` varchar(10) DEFAULT NULL COMMENT '对别的评论发表的二级评论的id,可以为空',
  `publish_time` int unsigned NOT NULL COMMENT '发表评论的时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=utf8;

visitor_like表

20220213180350.jpg

-- ----------------------------
-- Table structure for visitor_like
-- ----------------------------
DROP TABLE IF EXISTS `visitor_like`;
CREATE TABLE `visitor_like` (
  `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '访客点赞表id',
  `comment_id` int unsigned DEFAULT NULL COMMENT '评论id',
  `visitor_id` int unsigned DEFAULT NULL COMMENT '访客id',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=48 DEFAULT CHARSET=utf8;

后端逻辑代码地址:https://github.com/programmerMark/easyblog/blob/master/service/app/controller/blog/comment.js(使用egg.js)

这里,我简单分析下我的前端组件设计逻辑,不展开分析具体代码。

我的设计逻辑很简单。整个评论组件在功能上可以划分为三块:发表评论、用户登录弹窗、评论列表。根据功能和作为设计稿的掘金,可以拆分出三个子组件:用户登录弹窗(comment-modal)、发表评论(comment-input)、单条评论(comment-item)。

其中用户登录弹窗可以在用户任意发表评论是弹出用于共用,而发表评论组件在单条评论组件点击评论图标时触发,单条评论组件在只有两级的评论中只需要遍历两层即可。

技术推荐


文章的最后,我推荐一下我在这个功能中使用到的好用的前端技术和学习资源,或许这才是更干的干货。如果您觉得这篇有趣或者对你有帮助,不要吝啬你的点赞和评论。也欢迎在我的博客和我交流和试用这个评论功能。我的博客:https://immortalboy.cn/about

推荐技术:

tailwindcss

学习资源(推荐按顺序学习):

入门视频教程(使用YouTube自动生成英文字幕,并翻译字幕,英文不是问题):

www.youtube.com/watch?v=elg…

中文文档(tailwindcss2.0,依旧可以使用2.0的文档学习主要特性):

Tailwind CSS - 无需离开您的HTML,即可快速建立现代网站。

英文文档(最新版tailwindcss3.0):

Tailwind CSS - Rapidly build modern websites without ever leaving your HTML.

What's new in Tailwind CSS v3.0?

www.youtube.com/watch?v=mSC…

推荐技术:

vue-queryreact-query

说明一下:vue-query是react-query原作者开发的vue3版本,主要特性和用法基本一致;下面我会推荐一个好的react-query视频教程和vue-query需要注意的点。

学习资源(推荐按顺序学习):

入门视频教程(使用YouTube自动生成英文字幕,并翻译字幕,英文不是问题):

React Query Tutorial - 1 - Introduction

认识client state和server state(对client state和server state疑惑可以看):

www.youtube.com/watch?v=seU…

react-query中文文档:

概览 | React Query 中文文档

react-query官方文档:

React Query

vue-query官方文档:

Vue Query

vue-query在vue3中使用需要注意的点:

20220213183450.jpg 20220213183450.jpg

注意点文档地址:

Vue Query

推荐工具:

create-vue:快速创建vue项目

github.com/vuejs/creat…

原文地址


个人博客:

爱编程的Mark - 持续分享的前端工程师

notion地址(需l外网):

实现仿掘金的评论功能