一、开始
安装以下依赖:
npm i draft-js react-draft-wysiwyg draftjs-to-html html-to-draftjs
引入:
// 核心
import { EditorState, convertToRaw, ContentState } from 'draft-js'
import { Editor } from 'react-draft-wysiwyg'
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
// draft 转换为 html
import draftToHtml from 'draftjs-to-html'
// html 转换为 draft
import htmlToDraft from 'html-to-draftjs'
二、创建一个组件
export default class BraftEditors extends React.Component {
constructor(props) {
super(props)
this.state = {
// 创建一个空富文本
editorState: EditorState.createEmpty()
}
}
componentDidMount() {
// 如果从后台读取接口存储的有值,读取过来转换为富文本格式默认显示
if (this.props.htmlContent) {
this.toDraft(this.props.htmlContent)
}
}
onEditorStateChange = (editorState) => {
this.toHtml(editorState)
this.setState({
editorState
})
}
editorChange = value => {
console.log(value)
}
// 转换为 html
toHtml = value => {
let templateContent = draftToHtml(convertToRaw(value.getCurrentContent()))
if (this.props.getHtml) {
// 输出已经编辑好的html
this.props.getHtml(templateContent)
}
}
// 转换为 Draft
toDraft = value => {
const blocksFromHtml = htmlToDraft(value);
const { contentBlocks, entityMap } = blocksFromHtml;
const contentState = ContentState.createFromBlockArray(contentBlocks, entityMap);
const editorState = EditorState.createWithContent(contentState);
console.log(editorState)
this.setState({
editorState
})
}
imgFileupOnChange = (files) => {
// 返回值 files 就是上传的文件,控件会默认 Promise 返回,否则无法抓到返回的已上传图片链接
return new Promise(
(resolve, rejects) => {
// 使用 form 表单的形式进行配置,具体参数根据接口来
let formData = new FormData()
formData.append('File', files)
formData.append('FileType', 'Thumbnail')
formData.append('IsLogin', true)
formData.append('Description', '')
new Ajax({
// 这里是配置自己的图片上传链接
url: `/api/file/upload`,
method: 'post',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: formData
})
.start()
.then(res => (res = res.data))
.then(res => {
if (res.Status === 0) {
// Message.success('上传成功!')
resolve({ data: { link: res.Result } })
} else {
// Message.fail('上传失败!')
}
})
}
)
}
render() {
const { editorState } = this.state
const setToolbar = {
colorPicker: {
// 图标可以自定义,如果使用默认就注释掉
// icon: 'https://-------',
className: undefined,
component: undefined,
popupClassName: undefined,
// 图片选项卡自定义
colors: ['rgb(97,189,109)', 'rgb(26,188,156)', 'rgb(84,172,210)', 'rgb(44,130,201)',
'rgb(147,101,184)', 'rgb(71,85,119)', 'rgb(204,204,204)', 'rgb(65,168,95)', 'rgb(0,168,133)',
'rgb(61,142,185)', 'rgb(41,105,176)', 'rgb(85,57,130)', 'rgb(40,50,78)', 'rgb(0,0,0)',
'rgb(247,218,100)', 'rgb(251,160,38)', 'rgb(235,107,86)', 'rgb(226,80,65)', 'rgb(163,143,132)',
'rgb(239,239,239)', 'rgb(255,255,255)', 'rgb(250,197,28)', 'rgb(243,121,52)', 'rgb(209,72,65)',
'rgb(184,49,47)', 'rgb(124,112,107)', 'rgb(209,213,216)', 'rgb(0,0,0)'],
},
image: {
// icon: image,
className: undefined,
component: undefined,
popupClassName: undefined,
urlEnabled: true,
uploadEnabled: true,
alignmentEnabled: true,
uploadCallback: this.imgFileupOnChange,
previewImage: true,
inputAccept: 'image/gif,image/jpeg,image/jpg,image/png',
alt: { present: false, mandatory: false },
// 富文本中默认的图片尺寸,或写入到生成img标签的行间样式
defaultSize: {
height: 'auto',
width: 'auto',
},
},
}
return (
<div className="editor-wrap">
<Editor
editorState={editorState}
wrapperClassName="contract-template-add-wrapper"
editorClassName="contract-template-editor"
// toolbarClassName="toolbarClassName"
// wrapperClassName="wrapperClassName"
// editorClassName="editorClassName"
onEditorStateChange={this.onEditorStateChange}
onChange={this.editorChange}
toolbar={setToolbar}
/>
</div>
)
}
}
BraftEditors.propTypes = {
htmlContent: PropTypes.string,
getHtml: PropTypes.func
}
三、各函数、配置功能
onEditorStateChange
用于检测文本框中的值变化,然后再赋值给组件
editorChange
可忽略,类输入框检测变化,暂未使用
toolbar
这里边是自定义配置项,类似于图片上传和颜色选择配置都可以在这里斌完成,实例中列出了两种配置
imgFileupOnChange
上传图片配置,其中返回参数一定是固定的格式:
{ data: { link: res.Result } }
否则无法预览
其它函数请看代码注释,其它详细配置请参考官网:
https://jpuri.github.io/react-draft-wysiwyg/#/docs
四、删除一些不想留的配置项
用了样式的方法移除的,直接 display:none; 掉,可以参考:
.rdw-inline-wrapper{
// 隐藏删除按钮
[title=Strikethrough]{
display: none;
}
// 代码
[title=Monospace]{
display: none;
}
// 上角标
[title=Superscript]{
display: none;
}
// 下角标
[title=Subscript]{
display: none;
}
}
// 标签
.rdw-block-wrapper{
display: none;
}
// 字体
.rdw-fontfamily-wrapper{
display: none;
}
.rdw-embedded-wrapper{
display: none;
}
.rdw-list-wrapper{
[title=Indent]{
display: none;
}
[title=Outdent]{
display: none;
}
}