最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 基于React的富文本编辑器-Braft Editor使用

    正文概述 掘金(z止于至善)   2021-05-17   808

    antd 是基于 Ant Design 设计规范实现的 高质量 React 组件库,我们倾向于只提供符合该规范且带有视觉展现的 UI 组件,也尽量不重复造轮子。

    如果要在React项目中使用富文本编辑器,官方推荐使用react-quill 与 braft-editor。 详细点击这里

    这篇文章主要介绍Braft Editor与Antd的结合使用。

    在Ant Design表单中使用

    功能要点

    • 使用BraftEditor.createEditorState创建editorState
    • 使用editorState.toHTML()实时获取html
    • 使用editorState.isEmpty()进行空值校验

    注意事项

    • 编辑器组件的数据格式为ediorState,为此在调用setFieldsValue时和在提交之前,需要进行相应的转换(toHTML())
    • 进行空值校验的话,需要自定义validator,并通过value.isEmpty()来校验,value就是一个editorState
    • 编辑器组件的验证时机需要改成onBlur,以避免不期望的验证提示和不必要的性能开销
    • 编辑器的value属性必须是一个editorState对象
    • 实际使用时请避免在onChange中直接toHTML,配合节流函数或者在合适的时机使用更恰当

    编辑器演示

    基于React的富文本编辑器-Braft Editor使用

    示例源码

    import BaseCmp from '@components/BaseCmp.js'
    import { connect } from 'react-redux'
    import {
        RLInput, RLButton, RLForm, RLFormItem
    } from '@components/index.js'
    import { DatePicker } from 'antd'
    import { createRef } from 'react'
    import BraftEditor from 'braft-editor'
    import actionInfoManage from '@actions/infoManage/actionInfoManage.js'
    import { dealTime, dealDateTime } from '@/libs/utils.js'
    import moment from 'moment'
    import locale from 'antd/es/date-picker/locale/zh_CN'
    
    
    class CmpInfoEdit extends BaseCmp {
        constructor(props) {
            super(props)
            if (props.infoId) {
                this.infoId = props.infoId
            }
            this.state = {
                infoListInfo: {
                    title: '',
                    start_time: '',
                    content: BraftEditor.createEditorState(null)
                }
            }
            this.form = createRef()
        }
        componentDidMount() {
            if (this.infoId) {   // 编辑
                this.getInfoDetail(this.infoId)
            } else {
                this.setState({
                    infoListInfo: {
                        ...this.state.infoListInfo
                    }
                })
            }
        }
    
        // 资讯详情
        getInfoDetail = (id) => {
            actionInfoManage.getInfoDetail({id}).then(res => {
                if (res.code === 200) {
                    const data = res.data
                    let userList = data.invite_uids
                    this.setState({
                        userList,
                        infoListInfo: {
                            ...data,
                            start_time: moment(dealTime(data.start_time, 'YYYY-MM-DD HH:mm')),
                            content: BraftEditor.createEditorState(data.content),
                        }
                    }, () => {
                        // 给表单重置值
                        this.form && this.form.setFieldsValue(this.state.infoListInfo)
                    })
                } else {
                    this.showToast({ type: 'error', content: res.msg })
                }
            })
        }
    
        editFailed = (res) => {
            this.showToast({ content: '您有必填项未填写', type: 'success' })
        }
    
        editConfirm = (values) => {
            console.log('onFinish', values)
            this.setState({
                addLoading: true
            })
            let { start_time } = values
            const { title, content } = this.state.infoListInfo
            const params = {
                title,
                start_time: dealDateTime(start_time.format('YYYY-MM-DD HH:mm')),
                content: content.toHTML()
            }
            if (this.infoId) {   // 编辑
                actionInfoManage.infoEdit({ ...params, id: this.infoId }).then(res => {
                    if (res.code === 200) {
                        this.showToast({ content: '编辑成功', type: 'success' })
                        this.props.changePage('list')
                    } else {
                        this.showToast({ type: 'error', content: res.msg })
                    }
                }).finally(() => {
                    this.setState({
                        addLoading: false
                    })
                })
            } else {   // 创建
                actionInfoManage.infoAdd(params).then(res => {
                    if (res.code === 200) {
                        this.showToast({ type: 'success', content: '创建成功' })
                        this.props.changePage('list')
                    } else {
                        this.showToast({ type: 'error', content: res.msg })
                    }
                }).finally(() => {
                    this.setState({
                        addLoading: false
                    })
                })
            }
        }
    
        disabledDate = (current) => {
            return current && current < moment().startOf('day')
        }
    
        render() {
            return (
                <div className='page-info-edit'>
                    <RLForm
                        ref={form => this.form = form}
                        labelCol={{ style: { width: 150, marginRight: 20, textAlign: 'right' } }}
                        labelAlign='left'
                        wrapperCol={{ style: { span: 24, marginRight: 30 } }}
                        onFinish={this.editConfirm}
                        onFinishFailed={this.editFailed}
                        initialValues={this.state.infoListInfo}
                        validateTrigger='onBlur'
                    >
                        <RLFormItem
                            name='title'
                            label='资讯主题'
                            colon={false}
                            rules={[
                                {
                                    required: true,
                                    message: '请输入资讯主题'
                                }, {
                                    max: 50,
                                    message: '资讯主题最多50个字符'
                                }
                            ]}
                        >
                            <RLInput
                                placeholder='请输入资讯主题'
                                style={{ width: 360 }}
                                value={this.state.infoListInfo.title}
                                onChange={e => {
                                    this.setState({
                                        infoListInfo: {
                                            ...this.state.infoListInfo,
                                            title: e.target.value
                                        }
                                    })
                                }}
                            />
                        </RLFormItem>
                        <RLFormItem
                            name='start_time'
                            label='发布时间'
                            colon={false}
                            rules={[
                                {
                                    required: true,
                                    message: '请选择发布时间'
                                }
                            ]}
                        >
                            <DatePicker
                                allowClear
                                locale={locale}
                                showTime
                                disabledDate={this.disabledDate}
                                format={'YYYY-MM-DD HH:mm'}
                                placeholder='请选择日期时间'
                            />
                        </RLFormItem>
                        <RLFormItem
                            name='content'
                            label='正文内容'
                            colon={false}
                            rules={[
                                {
                                    required: true,
                                    validator: (rule, value) => {
                                        if (value.isEmpty()) {
                                            return Promise.reject('请输入正文内容')
                                        } else {
                                            return Promise.resolve()
                                        }
                                    }
                                }
                            ]}
                        >
                            <BraftEditor
                                value={this.state.infoListInfo.content}
                                onChange={editorState => {
                                    this.setState({
                                        infoListInfo: {
                                            ...this.state.infoListInfo,
                                            content: editorState
                                        }
                                    })
                                }}
                                media={{
                                    accepts: {
                                        image: 'image/jpeg,image/png',
                                        video: 'video/mp4',
                                        audio: 'audio/mpeg,audio/mp3',
                                    },
                                    uploadFn: (upload) => {},
    
                                    // onChange(...rest) {
                                    //     console.log('onChange---rest', rest)
                                    // }
                                }}
                                style={{ border: '1px solid #d1d1d1', borderRadius: 3, background: '#fff' }}
                            />
                        </RLFormItem>
    
                        <RLFormItem>
                            <div style={{ display: 'flex', justifyContent: 'center' }}>
                                <RLButton
                                    type="default"
                                    label='取消'
                                    width={80}
                                    style={{ display: 'inline-block' }}
                                    onClick={() => {
                                        this.props.changePage('list')
                                    }}
                                />
                                <RLButton
                                    type="primary"
                                    htmlType="submit"
                                    label={this.infoId ? '保存' : '创建'}
                                    style={{ marginLeft: 40, display: 'inline-block' }}
                                    loading={this.state.addLoading}
                                    width={80}
                                />
    
                            </div>
    
                        </RLFormItem>
                    </RLForm>
                </div>
            )
        }
    
    }
    export default connect((store, props) => {
        return {
            ...props
        }
    })(CmpInfoEdit)
    

    空值校验

    使用isEmpty()校验,rules中的代码如下:

    rules={[
        {
            required: true,
            validator: (rule, value) => {
                if (value.isEmpty()) {
                    return Promise.reject('请输入正文内容')
                } else {
                    return Promise.resolve()
                }
            }
        }
    ]}
    

    起源地下载网 » 基于React的富文本编辑器-Braft Editor使用

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元