Comment评论

对网站内容的反馈、评价和讨论。

何时使用

评论组件可用于对事物的讨论,例如页面、博客文章、问题等等。

代码演示

Comment评论 - 图1

基本评论

一个基本的评论组件,带有作者、头像、时间和操作。

  1. import React, { createElement, useState } from 'react';
  2. import { Comment, Tooltip, Avatar } from 'antd';
  3. import moment from 'moment';
  4. import { DislikeOutlined, LikeOutlined, DislikeFilled, LikeFilled } from '@ant-design/icons';
  5. const Demo = () => {
  6. const [likes, setLikes] = useState(0);
  7. const [dislikes, setDislikes] = useState(0);
  8. const [action, setAction] = useState(null);
  9. const like = () => {
  10. setLikes(1);
  11. setDislikes(0);
  12. setAction('liked');
  13. };
  14. const dislike = () => {
  15. setLikes(0);
  16. setDislikes(1);
  17. setAction('disliked');
  18. };
  19. const actions = [
  20. <span key="comment-basic-like">
  21. <Tooltip title="Like">
  22. {createElement(action === 'liked' ? LikeFilled : LikeOutlined, {
  23. onClick: like,
  24. })}
  25. </Tooltip>
  26. <span className="comment-action">{likes}</span>
  27. </span>,
  28. <span key="comment-basic-dislike">
  29. <Tooltip title="Dislike">
  30. {React.createElement(action === 'disliked' ? DislikeFilled : DislikeOutlined, {
  31. onClick: dislike,
  32. })}
  33. </Tooltip>
  34. <span className="comment-action">{dislikes}</span>
  35. </span>,
  36. <span key="comment-basic-reply-to">Reply to</span>,
  37. ];
  38. return (
  39. <Comment
  40. actions={actions}
  41. author={<a>Han Solo</a>}
  42. avatar={
  43. <Avatar
  44. src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
  45. alt="Han Solo"
  46. />
  47. }
  48. content={
  49. <p>
  50. We supply a series of design principles, practical patterns and high quality design
  51. resources (Sketch and Axure), to help people create their product prototypes beautifully
  52. and efficiently.
  53. </p>
  54. }
  55. datetime={
  56. <Tooltip title={moment().format('YYYY-MM-DD HH:mm:ss')}>
  57. <span>{moment().fromNow()}</span>
  58. </Tooltip>
  59. }
  60. />
  61. );
  62. };
  63. ReactDOM.render(<Demo />, mountNode);
  1. /* tile uploaded pictures */
  2. .comment-action {
  3. padding-left: 8px;
  4. cursor: 'auto';
  5. }
  6. [class*='-col-rtl'] .comment-action {
  7. padding-right: 8px;
  8. padding-left: 0;
  9. }

Comment评论 - 图2

配合 List 组件

配合 List 组件展现评论列表。

  1. import { Comment, Tooltip, List } from 'antd';
  2. import moment from 'moment';
  3. const data = [
  4. {
  5. actions: [<span key="comment-list-reply-to-0">Reply to</span>],
  6. author: 'Han Solo',
  7. avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png',
  8. content: (
  9. <p>
  10. We supply a series of design principles, practical patterns and high quality design
  11. resources (Sketch and Axure), to help people create their product prototypes beautifully and
  12. efficiently.
  13. </p>
  14. ),
  15. datetime: (
  16. <Tooltip
  17. title={moment()
  18. .subtract(1, 'days')
  19. .format('YYYY-MM-DD HH:mm:ss')}
  20. >
  21. <span>
  22. {moment()
  23. .subtract(1, 'days')
  24. .fromNow()}
  25. </span>
  26. </Tooltip>
  27. ),
  28. },
  29. {
  30. actions: [<span key="comment-list-reply-to-0">Reply to</span>],
  31. author: 'Han Solo',
  32. avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png',
  33. content: (
  34. <p>
  35. We supply a series of design principles, practical patterns and high quality design
  36. resources (Sketch and Axure), to help people create their product prototypes beautifully and
  37. efficiently.
  38. </p>
  39. ),
  40. datetime: (
  41. <Tooltip
  42. title={moment()
  43. .subtract(2, 'days')
  44. .format('YYYY-MM-DD HH:mm:ss')}
  45. >
  46. <span>
  47. {moment()
  48. .subtract(2, 'days')
  49. .fromNow()}
  50. </span>
  51. </Tooltip>
  52. ),
  53. },
  54. ];
  55. ReactDOM.render(
  56. <List
  57. className="comment-list"
  58. header={`${data.length} replies`}
  59. itemLayout="horizontal"
  60. dataSource={data}
  61. renderItem={item => (
  62. <li>
  63. <Comment
  64. actions={item.actions}
  65. author={item.author}
  66. avatar={item.avatar}
  67. content={item.content}
  68. datetime={item.datetime}
  69. />
  70. </li>
  71. )}
  72. />,
  73. mountNode,
  74. );

Comment评论 - 图3

嵌套评论

评论可以嵌套。

  1. import { Comment, Avatar } from 'antd';
  2. const ExampleComment = ({ children }) => (
  3. <Comment
  4. actions={[<span key="comment-nested-reply-to">Reply to</span>]}
  5. author={<a>Han Solo</a>}
  6. avatar={
  7. <Avatar
  8. src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
  9. alt="Han Solo"
  10. />
  11. }
  12. content={
  13. <p>
  14. We supply a series of design principles, practical patterns and high quality design
  15. resources (Sketch and Axure).
  16. </p>
  17. }
  18. >
  19. {children}
  20. </Comment>
  21. );
  22. ReactDOM.render(
  23. <ExampleComment>
  24. <ExampleComment>
  25. <ExampleComment />
  26. <ExampleComment />
  27. </ExampleComment>
  28. </ExampleComment>,
  29. mountNode,
  30. );

Comment评论 - 图4

回复框

评论编辑器组件提供了相同样式的封装以支持自定义评论编辑器。

  1. import { Comment, Avatar, Form, Button, List, Input } from 'antd';
  2. import moment from 'moment';
  3. const { TextArea } = Input;
  4. const CommentList = ({ comments }) => (
  5. <List
  6. dataSource={comments}
  7. header={`${comments.length} ${comments.length > 1 ? 'replies' : 'reply'}`}
  8. itemLayout="horizontal"
  9. renderItem={props => <Comment {...props} />}
  10. />
  11. );
  12. const Editor = ({ onChange, onSubmit, submitting, value }) => (
  13. <>
  14. <Form.Item>
  15. <TextArea rows={4} onChange={onChange} value={value} />
  16. </Form.Item>
  17. <Form.Item>
  18. <Button htmlType="submit" loading={submitting} onClick={onSubmit} type="primary">
  19. Add Comment
  20. </Button>
  21. </Form.Item>
  22. </>
  23. );
  24. class App extends React.Component {
  25. state = {
  26. comments: [],
  27. submitting: false,
  28. value: '',
  29. };
  30. handleSubmit = () => {
  31. if (!this.state.value) {
  32. return;
  33. }
  34. this.setState({
  35. submitting: true,
  36. });
  37. setTimeout(() => {
  38. this.setState({
  39. submitting: false,
  40. value: '',
  41. comments: [
  42. {
  43. author: 'Han Solo',
  44. avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png',
  45. content: <p>{this.state.value}</p>,
  46. datetime: moment().fromNow(),
  47. },
  48. ...this.state.comments,
  49. ],
  50. });
  51. }, 1000);
  52. };
  53. handleChange = e => {
  54. this.setState({
  55. value: e.target.value,
  56. });
  57. };
  58. render() {
  59. const { comments, submitting, value } = this.state;
  60. return (
  61. <>
  62. {comments.length > 0 && <CommentList comments={comments} />}
  63. <Comment
  64. avatar={
  65. <Avatar
  66. src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
  67. alt="Han Solo"
  68. />
  69. }
  70. content={
  71. <Editor
  72. onChange={this.handleChange}
  73. onSubmit={this.handleSubmit}
  74. submitting={submitting}
  75. value={value}
  76. />
  77. }
  78. />
  79. </>
  80. );
  81. }
  82. }
  83. ReactDOM.render(<App />, mountNode);

API

参数说明类型默认值版本
actions在评论内容下面呈现的操作项列表Array-
author要显示为注释作者的元素string|ReactNode-
avatar要显示为评论头像的元素 - 通常是 antd Avatar 或者 srcstring|ReactNode-
children嵌套注释应作为注释的子项提供ReactNode-
content评论的主要内容string|ReactNode-
datetime展示时间描述string|ReactNode-