想间接看实现的请跳过前三节 …..
需要形容
因为业务需要,须要用到比拟多的富文本编辑器,至于为什么会在一个页面里有很多的富文本,憋问我,问就是甲方爸爸给钱了!在富文本中,须要满足可能随便的批改图片的大小,可能间接复制图片进入,可能满足根本的排版需要,按理来说基本上网上的编辑器都能满足要求。
呈现的问题
而后我问了公司的其余共事,有什么比拟好的举荐,说了几个,最初我还是抉择了最简略的 wangEditor (过后我感觉它最简略,因为不须要怎么配置,网站也有现成的 demo
), 一开始是很顺畅的,可能灵便的设置菜单和根本响应,解决机制等,然而当我在一个页面中应用两个富文本时,出 bug 了,具体形容单击链接跳转看。简略的说就是两个富文本不能同时承受拖拽进来的图片。
解决办法
至于解决办法,当然是先去 github
报个异样, 而后换一个编辑器看看,客户在等着,也没工夫钻研。随后我尝试了 antd 社区精选组件,外面有两个 react-quill 和 braft-editor,别离编写了 demo
,发现后者更满足我的我的项目需要。
代码
当初开始进入正题,我先对 braft-editor 进行了简答封装,因为它自带的上传是会将图片转成 base64
格局的, 与我的需要不符,并且如果间接传 base64
的字符串, 数据太大,很容易引起接口传输过慢,中断的问题。封装代码如下:
Editor 文件
/**
* @desc 新的 antd 富文本编辑器
* @name Editor
* @author Cyearn
* @date 2020/12/11
*/
import React, {Component} from 'react'
import BraftEditor from 'braft-editor' // 引入库
import 'braft-editor/dist/index.css' // 引入款式
import {apiPostUpload} from '@/api/load' // 引入本人的上传接口
import {isDev} from '@/utils' // 断定是否为开发模式的函数
import {message} from 'antd'
// 本地调试时的服务地址
const HOST = process.env.REACT_APP_DEFAULT_PROXY
class Editor extends Component {constructor(props) {super(props)
this.state = {
propValue: '', // 一个用来断定是否须要初始化编辑器的变量
editorState: BraftEditor.createEditorState(null), // 设置编辑器初始内容
outputHTML: null, // 富文本的内容
}
this.editorRef = React.createRef() // 因为用到了自定义的上传,所以对编辑器加了一个 ref}
componentDidMount() {}
// 用来断定是否须要初始化编辑器
componentDidUpdate() {if (this.props.value && this.props.value !== this.state.propValue) {if (this.state.propValue === '') {
// 下层传入的是字符串构造的数据,所以须要应用 BraftEditor.createEditorState 来包裹它
this.setState({editorState: BraftEditor.createEditorState(this.props.value), propValue: this.props.value })
}
}
}
// 编辑器发生变化
handleChange = async editorState => {
await this.setState({
editorState: editorState,
outputHTML: editorState.toHTML(),})
this.props.onChange(editorState.toHTML()) // 当编辑器内容发生变化的时候向上抛出更改的后果
}
// 编辑器失去焦点
onBlurEditor = () => {const { outputHTML} = this.state
// this.props.onChange(outputHTML)
}
// 上传函数
uploadImage = async param => {
try {
let agr = {
file: param.file,
isOpenFile: true,
}
const res = await apiPostUpload(agr) // 本人的上传接口
let data = res.datas
param.progress(100) // 显示实现上传的进度条
param.success({
url: isDev ? HOST + data.url : data.url,
meta: {
alt: data.name,
// loop: true, // 指定音视频是否循环播放
// autoPlay: true, // 指定音视频是否自动播放
// controls: true, // 指定音视频是否显示管制栏
},
})
const {getValue} = this.editorRef // 通过 ref 获取到以后的编辑器内的数据
this.handleChange(getValue()) // 调用数据更新的函数,很重要,不做这个会呈现保留后果和显示后果不匹配的状况
} catch (error) {
let msg = error + ',上传失败'
message.error(msg)
}
}
// 查看图片发生变化的函数
changeImage = async file => {console.log(file)
}
render() {const { editorState} = this.state
const {width = '100%', id = 'braft_editor', height = 600} = this.props // 定义一些默认的格局
// 这是配置本人菜单的局部,删除就是显示全菜单
const controls = [
{
key: 'bold',
text: <b> 加粗 </b>,
},
'italic',
'underline',
'separator',
'link',
'separator',
'media',
]
return (<div className='editor-wrapper' style={{ width: width, border: '1px solid #999999'}} id={id}>
<BraftEditor
ref={e => (this.editorRef = e)} // 回调 refs,用来绑定 ref
value={editorState}
onChange={this.handleChange}
controls={controls} // 用来配置本人的菜单
contentStyle={{height: 300, boxShadow: 'inset 0 1px 3px rgba(0,0,0,.1)' }} // 用来设置一些款式
media={{uploadFn: this.uploadImage, pasteImage: true, onChange: this.changeImage}} // 用来定义本人的上传函数
/>
</div>
)
}
}
export default Editor
Form 表单所在文件
// 构造函数
constructor(props) {super(props)
this.state = {content: ''}
this.formRef = React.createRef()}
// 当 form 发生变化
onFormChange = e => {console.log(e)
Boolean(e['content']) &&
this.setState({content: e['content'],
})
}
//...render 外部的代码
<Form
{...layout}
name='docForm'
style={{width: '100%'}}
ref={this.formRef}
scrollToFirstError={true}
onValuesChange={this.onFormChange}
>
<Form.Item
name={'content'}
label='内容编辑'
rules={[{ required: true, type: 'string', min: 1},
// 须要自定义一个校验函数,因为 braft-editor 默认文本就是 <p></p>,form 自带的校验不会断定为空
({getFieldValue}) => ({validator(rule, value) {console.log(value)
if (value === '<p></p>') {return Promise.reject('请输出文章内容')
} else {return Promise.resolve()
}
},
}),
]}
>
{/* <Editor width={'85%'} value={content} onChange={this.changeContent}/> 如果不在 form 中应用就要本人写受控变量和 chang 函数 */}
<Editor width={'85%'} />
</Form.Item>
</Form>