美文网首页前端
react-quill 富文本编辑器中自定义图片插入(图片上传)

react-quill 富文本编辑器中自定义图片插入(图片上传)

作者: 变态的小水瓶 | 来源:发表于2018-12-26 11:46 被阅读462次

    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属性变成一个链接地址。具体效果见如下图:

    react-quill自定义插入图片.gif

    这个方案实现需要如下几个步骤:

    第一步:

    在富文本配置的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/

    相关文章

      网友评论

        本文标题:react-quill 富文本编辑器中自定义图片插入(图片上传)

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