zhengyingya c595e28c88 fix:表情弹框可配置位置、头像变形、图片多选等 | 5 years ago | |
---|---|---|
assets | 5 years ago | |
lib | 5 years ago | |
public | 6 years ago | |
src | 5 years ago | |
.babelrc | 6 years ago | |
.eslintrc | 6 years ago | |
.gitignore | 5 years ago | |
CHANGELOG.md | 5 years ago | |
README.md | 5 years ago | |
config-overrides.js | 5 years ago | |
package.json | 5 years ago | |
version.ejs | 5 years ago |
通用评论系统及编辑器
version 1.0.4
import Comment, { Editor, RenderText } from 'comment';
# npm 安装
$ npm install git+https://git.links123.net/npm/comment.git --save
# yarn 安装
$ yarn add git+https://git.links123.net/npm/comment.git
然后在代码里面引入 comment
组件:
import Comment, { Editor } from 'comment'
// ...
render() {
return (
<Comment type={1} businessId="test">
<Editor />
</Comment>
)
}
注意:最后,还需要在 HTML 文件里面引入阿里云 OSS SDK <script src="http://gosspublic.alicdn.com/aliyun-oss-sdk.min.js"></script>
使用assets
分支的 ./assets/static
目录https://git.links123.net/npm/comment/src/branch/assets/assets/static的静态文件
assets
分支的 ./assets/static
目录: https://git.links123.net/npm/comment/src/branch/assets/assets/static。window.renderComment
方法并传入对应参数来渲染通用评论。参数列表:
id
: string, 必填, 渲染评论的节点的 IDtype
: number, 必填, 评论的 typebusinessId
: string, 选填, 评论的 businessId,默认 testAPI
: string, 选填, 评论的 businessId,默认 http://api.links123.net/comment/v1具体可参考 ./assets/example.html
。
例子如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>通用评论 demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="./static/css/comment.0.5.13.css" />
</head>
<body>
<div>
<h1>在非 React.js 项目中使用通用评论</h1>
<p>将其渲染到 id 为 `comment` 的节点上</p>
<div id="comment"></div>
</div>
<script src="http://gosspublic.alicdn.com/aliyun-oss-sdk.min.js"></script>
<script type="text/javascript" src="./static/js/comment.0.5.13.js"></script>
<script type="text/javascript">
// 调用 renderComment 这个方法,渲染通用评论
window.renderComment({
id: 'comment', // required, 渲染通用评论到 comment 这个节点,id 名称可 自定义
type: 1, // required, 评论的 type
businessId: 'test' // 评论的 businessId, 默认 test
API: 'http://api.links123.net/comment/v1', // API 前缀, 默认 http://api.links123.net/comment/v1
});
</script>
</body>
</html>
有的场景可能需要在一个页面上根据不同 bid 多次渲染评论,可以参考 ./assets/example/rerender.html
。
其方案就是,每次渲染之前,都清空之前渲染的节点内容,再重新渲染。否则 React 会任务两次 render 是同样的内容,就不渲染。
详解:
<!-- ... -->
<link rel="stylesheet" type="text/css" media="screen" href="./static/css/xxx.css" />
<!-- ... -->
<div id="RENDER_ELEMENT_WRAPPER"></div>
<!-- ... -->
<script type="text/javascript" src="./static/js/xxx.js"></script>
<!-- ... -->
var RENDER_ELEMENT_WRAPPER = 'RENDER_ELEMENT_WRAPPER'; // 渲染评论的父标签
var RENDER_ELEMENT_COMMENT = 'comment'; // 渲染评论的标签的 id
/**
* 根据 id 创建节点
* @param {string} id id
*/
function createElement(id) {
var node = document.createElement('div');
node.setAttribute("id", id);
document.getElementById(RENDER_ELEMENT_WRAPPER).appendChild(node);
}
/**
* 根据 id 删除子节点
* @param {string} id id
*/
function removeChild(id) {
var myNode = document.getElementById(id);
while (myNode.firstChild) {
myNode.removeChild(myNode.firstChild);
}
}
function main() {
document.getElementById('render').addEventListener('click', function() {
// 首先清空父标签的内容
removeChild(RENDER_ELEMENT_WRAPPER);
var id = RENDER_ELEMENT_COMMENT;
// 动态创建渲染评论的标签
createElement(id);
// 渲染评论
window.renderComment({
id: id,
type: 1,
businessId: 'test',
API: 'http://api.links123.net/comment/v1',
})
})
document.getElementById('re-render').addEventListener('click', function() {
removeChild(RENDER_ELEMENT_WRAPPER)
var id = RENDER_ELEMENT_COMMENT;
createElement(id)
window.renderComment({
id: id,
type: 1,
businessId: 'test1',
API: 'http://api.links123.net/comment/v1',
})
})
}
main();
assets 分支已修复。
master
分支的图片预览 container
样式和 boostrap 有冲突。在 fix/classname
分支对评论的样式名称做了修改,改为了 comment-image-preview-container
。
解决办法就是使用 fix/classname
分支中的静态文件:
尝试过使用 CSS Module 进行修改,不过改造量较大,改动的过程中影响了其他样式,所以暂时放弃了。
deprecated
的配置项表示不推荐使用,并且可能在将来版本中不再受支持。props | type | default | required | description | |
---|---|---|---|---|---|
type | number | true | 评论的 type | ||
businessId | string | true | 评论的 business id | ||
API | string | http://api.links123.net/comment/v1 | false | API 前缀 | |
showList | boolean | true | false | 是否显示评论列表 | |
showEditor | boolean | true | false | 是否显示评论输入框 | |
showAlertComment | boolean | false | false | 评论成功之后,是否通过 Antd 的 Message 组件进行提示 | |
showAlertReply | boolean | false | false | 回复成功之后,是否通过 Antd 的 Message 组件进行提示 | |
showAlertFavor | boolean | false | false | 点赞/取消点赞成功之后,是否通过 Antd 的 Message 组件进行提示 | |
showError | boolean | true | false | 是否使用Antd的Message组件提示错误信息 | |
onError | function(msg) | false | 错误回调, 出错了会被调用 | ||
userId | number | false | 用户id, comment内部不维护用户id, 调用组件时传递过来, 目前用于判断是否显示删除按钮 | ||
token | string | false | [deprecated] token,用于身份认证,非必须。默认使用 cookie | ||
pageType | string | more | false | 分页类别, more-加载更多 pagination-页码 | |
page | number | false | 页码受控模式,如果传递了此参数,则需要通过onPageChange回调手动维护page. | ||
limit | number | 10 | false | 一次加载的评论数量 | |
onGetMoreBtnClick | function() | false | 点击查看更多按钮的回调 | ||
onPageChange | function(page) | false | 页码发生变化时的回调,注意:分页数据获取还是在组件内部处理的 | ||
onDelete | function(type) | false | 评论或回复删除成功后的回调, type: “comment” | “reply” , 用于区分删除的是评论还是回复 | |
locales | string | 语言 | false | ||
businessUserId | number | false | 评论目标的用户id, 用于发送通知 | ||
onCountChange | function(count) | false | 评论数量发生变更时的回调(初次获取也会调用) |
props | type | default | required | description |
---|---|---|---|---|
rows | number | 5 | false | 编辑器的高度。默认情况下,回复评论/回复回复的编辑器会比评论的编辑器高度小一行 |
placeholder | string | 说点什么吧… | false | 评论的中的提示文字 |
showEmoji | boolean | true | false | 是否显示 Toolbar 中表情工具 |
showUpload | boolean | true | false | 是否显示 Toolbar 中 上传图片工具 |
maxUpload | number | 1 | false | 最大能够上传的图片数量 |
value | string | false | 编辑器的值。如果设置了该属性,则编辑器变为受控组件,需要父组件来维护 value | |
onChange | function(value) | false | 编辑器内容改变的回调函数 | |
onSubmit | function({ text, files }) | false | 点击提交按钮的回调函数,text 为编辑器的文本,files 为上传的文件列表 | |
beforeSubmit | function ({text,files}):Promise | false | 点击提交按钮后的钩子, 若Promise resolve false则不触发onSubmit函数, 主要用于控制默认的submit行为 | |
onCommentSuccess | function() | false | 提交评论成功后的回调 | |
btnSubmitText | string | 发表 | false | 提交按钮的文字 |
btnLoading | boolean | false | false | 按钮是否正在加载中 |
btnDisable | boolean | false | false | 按钮是否禁用 |
button | ReactNode | false | 按钮组件。如果上面几个 btn 相关的属性都无法满足要求,则可以使用 button 来自定义提交编辑器值的按钮 | |
emojiToolIcon | ReactNode | false | Toolbar 中表情的图标 | |
imageToolIcon | ReactNode | false | Toolbar 中上传文件的图标 | |
onRef | function | false | 传递子组件的引用 | |
closeUploadWhenBlur | boolean | false | 当 upload 失去焦点(鼠标点击非 Upload 的区域)的时候,是否自动关闭 Popover | |
showError | boolean | true | false | 是否使用Antd的Message组件提示错误信息, 主要是上传图片出错的情况 |
onError | function(msg,{response}) | false | 错误回调, 出错了会被调用, 主要是上传图片出错的情况 | |
maxLength | number | 140 | false | 限制最大输入字数 |
autoFocus | boolean | false | false | 编辑器自动聚焦 |
如果将 comment
作为通用评论组件,则不要使用 value
onChange
onSubmit
。因为组件内部,实现了通用评论的业务逻辑。
可以使用 value/onChange/onSubmit 的情况:
Editor
。即 import { Editor } from 'comment'
showList: false
// 单独使用 Editor
<Editor value={this.state.value} onChange={(v) => this.setState({ value })} />
// 不需要展示评论列表
<Comment type={1} showList={false}>
<Editor value={this.state.value} onChange={(v) => this.setState({ value })} />
</Comment>
如果使用 button
,则 btnLoading
btnDisable
btnSubmitText
都会失效。因为这些属性是针对于编辑器默认的提交按钮设置的。
所以如果要提交编辑器的值,需要自己在 Button
组件上实现提交功能。编辑器的值,可以通过 onChange
方法获取到。
如果使用了 button
属性,并且没有为其设置 onClick
方法,则 onClick
默认为发布评论,即点击按钮会发表评论:
// 如下代码所示
// 点击“自定义按钮”的时候,会发表评论。这是由 Comment 组件内部实现的业务逻辑
<Comment type={1} businessId="test" showList={false}>
<Editor
button={(
<Button
type="primary"
ghost
>
自定义按钮
</Button>
)}
/>
</Comment>
如果使用了 button
属性,并且设置了 onClick
方法,则会覆盖默认的 onClick
方法:
// 下面的代码,点击的时候,不会提交评论
// 而是会输出 state 的值(
// 即编辑器的值,因为 onChange 将编辑器输入的值通过回调函数传递给了父组件)
<Comment type={1} businessId="test" showList={false}>
<Editor
button={(
<Button
type="primary"
ghost
onChange={(value) => this.setState({ value })}
onClick={() => console.log(this.state.value)}
>
自定义按钮
</Button>
)}
value={this.state.value}
/>
</Comment>
如果你需要在父组件里面调用子组件的方法,就可以使用 onRef
。主要是用于调用 Editor 组件内部的 resetState
方法。
如果你需要在父组件里面,手动清空 Editor 里面的数据,则可以使用 resetState
。因为即使父组件传入了 value
, Editor 内部也会保存一份 value
的值,用于 onSubmit
回调将值传递给父组件。所以可能存在,当子组件值没有清除,而父组件的 value
为空的情况,导致编辑器中文字和实际预想的不一致。所以当在父组件里面使用了 value
并重置 value
的时候,最好清空 Editor 的 state。
具体使用方式如下:
handleChangeSubmit() {
// 点击按钮,调用 onSubmit 的时候,清空 Editor 的数据
this.editor.resetState();
}
<Comment type={1} businessId="test">
<Editor
// 使用 onRef 方法创建一个 Editor 组件的引用,并添加到 this 上面
onRef={ref => this.editor = ref }
onSubmit={() => this.handleChangeSubmit()}
/>
</Comment>
注意上面的 onRef={ref => this.editor = ref }
,这是实现父组件调用子组件方法的关键。**
import { RenderText } from 'comment';
render() {
return RenderText('test [呲牙]')
}
$ git clone https://git.links123.net/npm/comment
$ cd comment
$ yarn
$ yarn start
yarn build
将项目打包成一个单页应用yarn lib
将项目打包成一个 es5 组件yarn prettier
优化代码格式https://links123-images.oss-cn-hangzhou.aliyuncs.com/avatar/