react-quill 富文本编辑器插件是一款基础轻量的编辑器,引入也非常简单,如下:
import ReactQuill, { Quill } from 'react-quill';
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.state = { text: '' } // You can also pass a Quill Delta here
this.handleChange = this.handleChange.bind(this)
}
handleChange(value) {
this.setState({ text: value })
}
render() {
return (
<ReactQuill value={this.state.text}
onChange={this.handleChange} />
)
}
}
但是,编辑器中插入图片时,编辑器默认的处理是将图片转成base64保存,提交后端时请求数据太大,给数据库带来压力。
因此,进行改善,将图片先上传到数据库,使富文本编辑器里插入的img标签,src属性变成一个链接地址。具体效果见如下图:
这个方案实现需要如下几个步骤:
第一步:
在富文本配置的toolbar中增加handler对象,设置其image属性,用于自定义函数去覆盖默认的方法,此处为点击图片上传按钮时,显示一个弹框。
this.modules={//富文本配置
toolbar:{
container:[
[{ 'font': fonts }],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
['bold', 'italic', 'underline','strike', 'blockquote'],
[{ 'color': [] }, { 'background': [] }],
[{'list': 'ordered'}, {'list': 'bullet'}, {'indent': '-1'}, {'indent': '+1'},{ 'align': [] }],
['link', 'image'],
['clean'],
],
handlers: {
'image':this.showUploadBox.bind(this)
}
},
imageDrop: true,
};
//react组件中定义方法
showUploadBox(){
this.setState({
uploadBoxVisible:true
});
}
//react组件render 中return modal结构
<Modal
title="上传图片"
visible={this.state.uploadBoxVisible}
onCancel={this.hideUploadBox.bind(this)}
onOk={this.handleUpload.bind(this,this.state.uploadUrl,this.state.file)}
maskClosable={false}
width={500}
>
<div className="top_btn top_btn_upload" >
<div>
<Button onClick={this.selectImage.bind(this)} style={{background:"#18ade4",border:"none",color:"#fff"}}>
选择图片
</Button>
<input ref="uploadInput" type='file' accept='image/*'
style={{width:"100px",border:"none",visibility:"hidden"}}
onChange={this.changeImageBeforeUpload.bind(this)}
/>
</div>
<div style={{textAlign:"center",margin:"10px 0"}}>
{this.state.src?
<img src={this.state.src} alt="" style={{maxWidth:"100%",height:"300px"}}/>
:
<div style={{background:"#f2f2f2",width:"100%",height:"300px"}}>
</div>
}
</div>
</div>
</Modal>
第二步:
点击选择图片按钮时选择本地一张图片,具体实现代码如下:
//组件中定义选择图片的方法
selectImage(){
this.refs.uploadInput.click();//点击modal的html结构中的input标签
}
//如上modal中input标签
<input ref="uploadInput" type='file' accept='image/*'
style={{width:"100px",border:"none",visibility:"hidden"}}
onChange={this.changeImageBeforeUpload.bind(this)}
/>
选择好图片后会调用input的onChange回调函数,这个回调函数可以做一些判断,其内容如下:
changeImageBeforeUpload(e){
const file = e.target.files[0];
if (!file) {
return;
}
let src;
// 匹配类型为image/开头的字符串
if (file.type==="image/png"||file.type==="image/jpeg") {
src = URL.createObjectURL(file);
}else{
message.error("图片上传只支持JPG/PNG格式,请重新上传!");
return;
}
if (file.size/1024/1024>5) {
message.error("图片上传大小不要超过5MB,请重新上传!");
return;
}
this.setState({
src:src,
file:file
})
}
第三步:
选择好图片后,可以再选择图片进行替换,确认好后点击确认,进行图片上传。
/*开始上传图片*/
handleUpload(uploadUrl,file){
let this_=this;
/*调用上传图片的封装方法*/
uploadFunction.uploadForImage(
uploadUrl,
file,
function (response) {//回调函数处理进度和后端返回值
if (response&&response.code === 200) {
message.success("上传成功!");
this_.hideUploadBox();//隐藏弹框
this_.imageHandler(response.data.url);//处理插入图片到编辑器
}else if (response && response.code !== 200) {
message.error(response.msg)
}
},
localStorage.getItem("access_token"));
}
如上使用的图片上传封装方法如下,将后端返回的数据传输回调函数中:
function uploadForImage(url,data,callback,token) {//data是数据列表
console.log('post-请求接口:' + url);
console.log('请求参数:' + data);
let this_=this;
if (!data) {
console.log('未选择文件');
return;
}
let xhr = new XMLHttpRequest();
let form = new FormData();
form.append('file', data);
xhr.addEventListener('readystatechange',function(e){
console.log(e);
let response=e.target.response?JSON.parse(e.target.response):null;
console.log(response);
if (e.target.readyState===4&&response) {
callback(response);
}
},false);
xhr.open('POST', url, true); // 第三个参数为async?,异步/同步
xhr.setRequestHeader("accessToken",token);
xhr.send(form);
}
第四步:
处理插入图片到编辑器,第三步有一个函数imageHandler(response.data.url),其中,response.data.url为返回的图片地址,imageHandler内容如下:
/*处理图片插入*/
imageHandler(url){
let quill=this.refs.reactQuillRef.getEditor();//获取到编辑器本身
const cursorPosition =quill.getSelection().index;//获取当前光标位置
quill.insertEmbed(cursorPosition, "image",url, Quill.sources.USER);//插入图片
quill.setSelection(cursorPosition + 1);//光标位置加1
}
到此为止,功能实现。
可以查看官方文档了解更多:
react-quill:https://www.npmjs.com/package/react-quill#import-the-component
quill:https://quilljs.com/docs/quickstart/