富文本编辑vue-quill-editor自定义图片、文件上传

原文:https://www.jianshu.com/p/9e4e4d955d0f

需求一 图片上传

就是要一个富文本编辑器,然后有图片上传功能,因为vue-quill-editor是将图片转为base64编码,所以当图片比较大时,提交后台时参数过长,导致提交失败。

解决思路
将图片先上传至服务器,再将图片链接插入到富文本中
图片上传的话可以使用element或者iview,这里我以iview举例
图片上传区域要隐藏,自定义vue-quill-editor的图片上传,点击图片上传时调用iview或者element的图片上传,上传成功后在富文本编辑器中显示图片

步骤
零、安装使用

npm install vue-quill-editor --save
main.js
import VueQuillEditor from 'vue-quill-editor'
Vue.use(VueQuillEditor);
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
一、自定义vue-quill-editor图片上传

html:

<quill-editor
    v-model="content"
    :options="editorOption"
    ref="QuillEditor">
</quill-editor>
js:

<script>
    // 工具栏配置
    const toolbarOptions = [
      ['bold', 'italic', 'underline', 'strike'],        // toggled buttons
      ['blockquote', 'code-block'],
    
      [{'header': 1}, {'header': 2}],               // custom button values
      [{'list': 'ordered'}, {'list': 'bullet'}],
      [{'script': 'sub'}, {'script': 'super'}],      // superscript/subscript
      [{'indent': '-1'}, {'indent': '+1'}],          // outdent/indent
      [{'direction': 'rtl'}],                         // text direction
    
      [{'size': ['small', false, 'large', 'huge']}],  // custom dropdown
      [{'header': [1, 2, 3, 4, 5, 6, false]}],
    
      [{'color': []}, {'background': []}],          // dropdown with defaults from theme
      [{'font': []}],
      [{'align': []}],
      ['link', 'image', 'video'],
      ['clean']                                         // remove formatting button
    ]
    
    export default {
        data () {
            return {
                content: '',
                editorOption: {                
                    modules: {
                        toolbar: {
                            container: toolbarOptions,  // 工具栏
                            handlers: {
                                'image': function (value) {
                                    if (value) {
                                        alert('自定义图片')
                                    } else {
                                        this.quill.format('image', false);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }    
</script>

二、调用element或iview图片上传组件

html:

<Upload
    :show-upload-list="false"
    :on-success="handleSuccess"
    :format="['jpg','jpeg','png','gif']"
    :max-size="2048"
    multiple
    action="/file/upload"
    >
    <Button icon="ios-cloud-upload-outline" ></Button>
</Upload>
<quill-editor
    v-model="content"
    :options="editorOption"
    ref="QuillEditor">
</quill-editor>

css:

.ivu-upload {
    display: none;
}

js:

data () {
    return {
        content: '',
        editorOption: {                
            modules: {
                toolbar: {
                    container: toolbarOptions,  // 工具栏
                    handlers: {
                        'image': function (value) {
                            if (value) {
                                // 调用iview图片上传
                                document.querySelector('.ivu-upload .ivu-btn').click()
                            } else {
                                this.quill.format('image', false);
                            }
                        }
                    }
                }
            }
        }
    }
},
methods: {
    handleSuccess (res) {
        // 获取富文本组件实例
        let quill = this.$refs.QuillEditor.quill
        // 如果上传成功
        if (res) {
            // 获取光标所在位置
            let length = quill.getSelection().index;
            // 插入图片,res为服务器返回的图片链接地址
            quill.insertEmbed(length, 'image', res)
            // 调整光标到最后
            quill.setSelection(length + 1)
        } else {
            // 提示信息,需引入Message
            Message.error('图片插入失败')
        }
    },
} 

三、假如需要多个富文本编辑器
可能不止一处地方用到,比如添加完成后还有编辑功能,那就复制一份文件上传和富文本编辑:两个富文本用不同的ref标记,在各自配置中调用各自的文件上传;文件上传成功也使用不同的方法名称,里面调用各自的富文本编辑器。

重点:富文本和文件上传不管使用类名还是什么方式区分的,这两处地方都要和之前区分开。

需求二 文件上传

和图片上传相同,不同的是上传文件。解决的思路也相同:在vue-quill-editor中自定义按钮,点击使用iView的文件上传,然后将地址赋值给a标签的href属性,插入到富文本光标处。

步骤

一、自定义编辑器附件上传

我想通过download属性自定义文件下载名称,但是两种方式都失败了,可以忽略相关代码。以下是为富文本自定义插入a链接

 import { Quill } from 'vue-quill-editor';
  // 自定义插入a链接
  var Link = Quill.import('formats/link');
  class FileBlot extends Link {  // 继承Link Blot
    static create(value) {
      let node = undefined
      if (value&&!value.href){  // 适应原本的Link Blot
        node = super.create(value);
      }
      else{  // 自定义Link Blot
        node = super.create(value.href);
        // node.setAttribute('download', value.innerText);  // 左键点击即下载
        node.innerText = value.innerText;
        node.download = value.innerText;
      }
      return node;
    }
  }
  FileBlot.blotName = 'link';
  FileBlot.tagName = 'A';
  Quill.register(FileBlot);

配置工具栏,添加了一个upload,其余不需要的都可以去掉

<script>
    // 自定义插入a链接
    // ...
    // 工具栏配置
    const toolbarOptions = [
      ['bold', 'italic', 'underline', 'strike'],        // toggled buttons
      ['blockquote', 'code-block'],
    
      [{'header': 1}, {'header': 2}],               // custom button values
      [{'list': 'ordered'}, {'list': 'bullet'}],
      [{'script': 'sub'}, {'script': 'super'}],      // superscript/subscript
      [{'indent': '-1'}, {'indent': '+1'}],          // outdent/indent
      [{'direction': 'rtl'}],                         // text direction
    
      [{'size': ['small', false, 'large', 'huge']}],  // custom dropdown
      [{'header': [1, 2, 3, 4, 5, 6, false]}],
    
      [{'color': []}, {'background': []}],          // dropdown with defaults from theme
      [{'font': []}],
      [{'align': []}],
      ['link', 'image', 'upload'],
      ['clean']                                         // remove formatting button
    ]
    
    export default {
        data () {
            return {
                content: '',
                editorOption: {                
                    modules: {
                        toolbar: {
                            container: toolbarOptions,  // 工具栏
                            handlers: {
                                'image': ((value) => {
                                    if (value) {
                                        alert('自定义图片')
                                    } else {
                                        this.quill.format('image', false);
                                    }
                                }),
                                'upload': ((value) => {
                                    if (value) {
                                        alert('自定义文件上传')
                                    }
                                })
                            }
                        }
                    }
                }
            }
        }
    }    
</script>

自定义文件上传的图标样式

.ql-snow.ql-toolbar .ql-upload{
      background: url("../assets/images/icon-upload.svg");
      background-size: 16px 16px;
      background-position: center center;
      background-repeat:no-repeat;
      /*background: red;*/
}
二、调用element或iview上传组件

为两个图片上传分别定义了类名,以做调用时的区分。

  <!-- 上传图片 -->
    <Upload
      :show-upload-list="false"
      :on-success="handleSuccess"
      :format="messageAllData.imgFileType"
      :before-upload="handleBeforeUpload"
      type="drag"
      :action="api.imgManage"
      class="uploadImage">
    </Upload>
    <!-- 上传文件 -->
    <Upload :show-upload-list="false"
            :on-success="handleFileSuccess"
            :before-upload="handleFileBeforeUpload"
            type="drag"
            :action="api.imgManage"
            class="uploadFile">
    </Upload>

修改工具栏配置,当点击富文本时,调用相应的上传组件

handlers: {
  'image': (value => {
    if (value) {
      document.querySelector('.uploadImage input').click()
    }else {
      this.quill.format('image', false);
    }
  }),
  'upload': (value => {
    if (value) {
      document.querySelector('.uploadFile input').click()
    }
  })
}

这两个文件上传都要隐藏

.uploadImage,
.uploadFile{
    width: 0;
    height: 0;
    display: none;
}

下面是插入图片和文件的方法

<quill-editor
    v-model="content"
    :options="editorOption"
    ref="QuillEditor">
</quill-editor>
methods: {
   // 图片
   handleSuccess (res, file) {
        let quill = this.$refs.QuillEditor.quill
        let length = quill.getSelection().index;
        quill.insertEmbed(length, 'image', res)
        quill.setSelection(length + 1)
   },
   // 文件
   handleFileSuccess (res, file) {       
        let fileNameLength = file.name.length
        // 插入链接
        let quill = this.$refs.QuillEditor.quill
        let length = quill.getSelection().index;
        quill.insertEmbed(length, 'link', {href:res, innerText:file.name}, "api")
        quill.setSelection(length + fileNameLength)
   },
} 

bug及优化

一、回车光标不显示

不知道为什么,百度都搜不到,好像只有我出现了这个问题,最后通过监听回车,手动换行并在换行后加了一个空格,因为没有内容的时候光标不显示,然后把光标向前调一个位置,移到空格前面。

const bindings = {
    custom: {
      key: 13,
      handler: function(range, context) {
        this.quill.insertText(range.index, '\n ');
        setTimeout(() => {
          let nowRange = this.quill.getSelection().index - 1
          this.quill.setSelection(nowRange)
        }, 0)
      }
    },
}
    export default {
        data () {
            return {
                content: '',
                editorOption: {                
                    modules: {
                        keyboard: {
                            bindings: bindings
                        },
                        toolbar: {
                            // ...
                        }
                    }
                }
            }
        }
    }  
二、给菜单栏添加中文标题title
// 标题
const titleConfig = {
    'ql-bold':'加粗',
    'ql-color':'颜色',
    'ql-font':'字体',
    'ql-code':'插入代码',
    'ql-italic':'斜体',
    'ql-link':'添加链接',
    'ql-background':'背景颜色',
    'ql-size':'字体大小',
    'ql-strike':'删除线',
    'ql-script':'上标/下标',
    'ql-underline':'下划线',
    'ql-blockquote':'引用',
    'ql-header':'标题',
    'ql-indent':'缩进',
    'ql-list':'列表',
    'ql-align':'文本对齐',
    'ql-direction':'文本方向',
    'ql-code-block':'代码块',
    'ql-formula':'公式',
    'ql-image':'图片',
    'ql-video':'视频',
    'ql-clean':'清除字体样式',
    'ql-upload':'文件'
};

methods: {
    addQuillTitle () {
        const oToolBar = document.querySelector('.ql-toolbar'),
        aButton = oToolBar.querySelectorAll('button'),
        aSelect =  oToolBar.querySelectorAll('select');
        aButton.forEach(function(item){
          if(item.className === 'ql-script'){
              item.value === 'sub' ? item.title = '下标': item.title = '上标';
          }else if(item.className === 'ql-indent'){
              item.value === '+1' ? item.title ='向右缩进': item.title ='向左缩进';
          }else{
              item.title = titleConfig[item.classList[0]];
          }
        });
        aSelect.forEach(function(item){
            item.parentNode.title = titleConfig[item.classList[0]];
        });
    },
},
mounted () {
      this.addQuillTitle()
},

有个需要注意的地方,按上面的方法使用后,确实有效,但是字体颜色和背景颜色的提示都变成了背景颜色,然后修改了标题栏的配置,提示才彼此对应。

const toolbarOptions = [     
      [{'color': []}, {'background': []}],
]

修改为

const toolbarOptions = [     
      [{'color': []}],
      [{'background': []}],
]
页面展示

图片样式限制宽高和边距就可以了,在富文本编辑器里面可以回车换行;
方式一:
可以另写一个style标签里面写上样式,也可以在原有的样式中通过深度选择器来写样式

<div v-html="editorContent" class="richTextStyle"></div>
<style>
  /*富文本图片样式 */
  .richTextStyle img {
    max-width: 720px;
    margin:10px;
  }
  /*富文本文字溢出不换行样式 */
  .richTextStyle p, .richTextStyle sup, .richTextStyle strong,
  .richTextStyle em, .richTextStyle u,
  .richTextStyle s, .richTextStyle blockquote, 
  .richTextStyle h1, .richTextStyle h2, .richTextStyle h3,
  .richTextStyle h4, .richTextStyle h5, .richTextStyle h6, 
  .richTextStyle li, .richTextStyle sub, .richTextStyle a {
    word-break: break-all;
  }
</style>

方式二:
完全以原来的样式显示富文本

<div v-html="editorContent" class="ql-editor"></div>
  • 0
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Vue-Quill-Editor 是一个基于 Quill.js 的富文本编辑器,如果想要在编辑器中上传图片,可以自定义一个上传图片的方法。 首先,在 Vue-Quill-Editor 中定义一个上传图片的方法: ```javascript <template> <div ref="editor"> </div> </template> <script> import { quillEditor } from 'vue-quill-editor' export default { components: { quillEditor }, methods: { uploadImage(file) { const formData = new FormData() formData.append('file', file) // 发送请求上传文件 // 返回图片地址 return Promise.resolve('https://your-cdn.com/' + file.name) } } } </script> ``` 然后在 `quill-editor` 组件上设置 `:custom-options` 属性,将上传图片的方法传递给 Quill.js: ```javascript <quill-editor ref="myQuillEditor" :custom-options="{ modules: { toolbar: [ ['bold', 'italic', 'underline', 'strike'], [{ header: [1, 2, false] }], ['blockquote', 'code-block'], [{ list: 'ordered' }, { list: 'bullet' }], [{ script: 'sub' }, { script: 'super' }], [{ indent: '-1' }, { indent: '+1' }], [{ direction: 'rtl' }], [{ size: ['small', false, 'large', 'huge'] }], [{ header: [1, 2, 3, 4, 5, 6, false] }], [{ color: [] }, { background: [] }], [{ font: [] }], [{ align: [] }], ['clean'], ['link', 'image', 'video'] ], imageDrop: true, imageResize: {}, imageExtend: { loading: true, headers: { 'Authorization': 'Bearer ' + token }, url: 'https://your-api.com/upload/image', method: 'POST', size: 2 * 1024 * 1024, compress: true, convertSize: 1080, format: 'image/jpeg', altKey: true, responseFn: response => { // 返回图片地址 return 'https://your-cdn.com/' + response.data.url } } }, placeholder: '请输入内容', theme: 'snow' }" @ready="onEditorReady" ></quill-editor> ``` 这里主要是设置 `imageExtend` 属性,其中 `url` 属性为上传图片的接口地址, `responseFn` 为上传图片成功后返回的数据处理方法。 最后在 `uploadImage` 方法中发送请求上传图片,并返回图片地址即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值