美文网首页
React富文本插件:基于draft-js 的 react-dr

React富文本插件:基于draft-js 的 react-dr

作者: River_mx | 来源:发表于2019-11-29 15:16 被阅读0次

    一、开始

    安装以下依赖:

    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;
                    }
                }
    

    五、效果展示

    截屏2019-11-2915.44.56.png

    上边列举了最近开发使用到的部分功能,如果还有什么问题,欢迎留言~

    相关文章

      网友评论

          本文标题:React富文本插件:基于draft-js 的 react-dr

          本文链接:https://www.haomeiwen.com/subject/wyiwwctx.html