富文本编辑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:



js:



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

html:


    



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,其余不需要的都可以去掉


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

.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上传组件

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

  
    
    
    
    
    

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

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;
}

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



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标签里面写上样式,也可以在原有的样式中通过深度选择器来写样式

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

你可能感兴趣的:(Vue)