欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

vue使用富文本编辑器:vue-quill-editor粘贴图片+图片上传服务器

程序员文章站 2022-03-20 19:13:09
引入vue-quill-editor初始化vue-quill-editornpm install vue-quill-editor --save部分页面引入组件 import 'quill/dist/quill.core.css' import 'quill/dist/quill.snow.css' import 'quill/dist/quill.bubble.css' import {quillEditor} from 'vue-quill-editor'全局引入组件...

引入vue-quill-editor

  1. 初始化vue-quill-editor
npm install vue-quill-editor --save
  1. 部分页面引入组件
  import 'quill/dist/quill.core.css'
  import 'quill/dist/quill.snow.css'
  import 'quill/dist/quill.bubble.css'
  import {quillEditor} from 'vue-quill-editor'

全局引入组件

  • main.js文件中
import  VueQuillEditor from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
Vue.use(VueQuillEditor)

根据需求自定义富文本

  • 创建QuillEditorForm.vue和toolbarOptions.js,抽象成一个新的组件
  • 需求:图片通过右键粘贴、点击上方图片上传按钮进行上传。由于组件默认将图片转为base64再放入内容中,如果图片比较大的话,富文本的内容就会很大,即使图片不大,只要图片较为多,篇幅较长,富文本的内容也变大影响数据传递。所以只能传递到服务器上,然后将url赋值给img的src。监听粘贴事件自定义上传(这个解决方案想了很久)
  • show me the code
<template>
  <!--富文本编辑器-->
  <div class="app-container">
    <div class="avatar">
      <!-- 图片上传组件辅助-->
      <el-upload
        id="quill-upload"
        action="上传的路径"
        ref="annexUpload"
        name="content"
        :limit="1"
        list-type="picture"
        :on-exceed="handleExceed"
        :on-error="handleError"
        :on-success="uploadAttachment"
        :file-list="uploadList"
        :with-credentials="true"
        :auto-upload="true">
      </el-upload>
    </div>
    <el-row v-loading="quillUpdateImg">
      <div class="edit_container">
        <quill-editor
          :disabled="disableFlag"
          v-model="detailContent"
          ref="myQuillEditor"
          :options="editorOption"
          @change="onEditorChange($event)">
        </quill-editor>
      </div>
    </el-row>
  </div>

</template>
<script>
  import 'quill/dist/quill.core.css'
  import 'quill/dist/quill.snow.css'
  import 'quill/dist/quill.bubble.css'
  import {quillEditor} from 'vue-quill-editor'
  import toolbarOptions from './toolbarOptions'

  export default {
    name: 'QuillEditorForm',
    components: {
      quillEditor
    },
    props: ['entity', 'disableFlag', 'problemDescribe'],
    data() {
      return {
        quillUpdateImg: false, // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示
        uploadList: [],
        detailContent: '', // 富文本内容
        // 富文本编辑器配置
        editorOption: {
          placeholder: '',
          theme: 'snow',  // or 'bubble'
          modules: {
            toolbar: {
              container: toolbarOptions,  // 工具栏
              handlers: {
                'image': function(value) {
                  if (value) {
                  // 绑定上传图片按钮
                    document.querySelector('#quill-upload input').click()
                  } else {
                    this.quill.format('image', false)
                  }
                }
              }
            }
          }
        }
      }
    },
    mounted() {
      //  自定义粘贴图片功能
      let quill = this.$refs.myQuillEditor.quill
      if (!this.disableFlag) {
        toolbarOptions[0] = ['image']
      }
      this.$forceUpdate()
      quill.root.addEventListener('paste', evt => {
        if (evt.clipboardData && evt.clipboardData.files && evt.clipboardData.files.length) {
          evt.preventDefault();
          [].forEach.call(evt.clipboardData.files, file => {
            if (!file.type.match(/^image\/(gif|jpe?g|a?png|bmp)/i)) {
              return
            }
            this.uploadToServer(file, (res) => {
              // 获取光标内容
              var range = quill.getSelection()
              if (range) {
                this.uploadAttachment(res, file, null)
                //  将光标移动到图片后面
                this.$refs.myQuillEditor.quill.setSelection(range.index + 1)
              }
            })
          })
        }
      }, false)
    },
    methods: {
      uploadToServer(file, callback) {
        var xhr = new XMLHttpRequest()
        var formData = new FormData()
        formData.append('content', file)
        xhr.open('post', '服务器路径')
        xhr.withCredentials = true
        xhr.responseType = 'json'
        xhr.send(formData)
        xhr.onreadystatechange = () => {
          if (xhr.readyState === 4 && xhr.status === 200) {
            callback(xhr.response)
          }
        }
      },
      handleExceed(files, fileList) {
        this.$message.warning(`当前限制一次性上传最多 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
      },
      handleError(err, file, fileList) {
        this.$message.warning(`文件上传失败,请尝试重新上传,文件失败原因为: ${err}`)
      },
      uploadAttachment(response, file, fileList) {
        // 保存文件信息
        if (response.status.code === 0) {
          // 获取富文本组件实例
          let quill = this.$refs.myQuillEditor.quill
          // 获取光标所在位置
          let length = quill.getSelection().index
          // 插入图片  res.info为服务器返回的图片地址
          quill.insertEmbed(length, 'image', response.url)
          quill.setSelection(length + 1)
          let fileType = null
          if (file.raw && file.raw.type) {
            fileType = file.raw.type
          } else {
            fileType = file.type
          }
          let params = {}
          params = {
           // 保存文件上传的参数
          }
          workService.create(params).then((res) => {
            this.$message.success('上传成功')
          }).catch((err) => {
            this.$message.error(err)
          })
        } else {
          this.$message.error(response.status.message)
        }
        // 清空文件列表
        this.uploadList = []
      },
      onEditorChange(e) {
        this.$emit('change', e.html)
      }
    }
  }
</script>

<style scoped>

  .quill-editor {
    min-width: 600px;
    max-width: 700px;
    max-height: 250px;
    overflow: auto;
  }

  .avatar {
    display: none;
  }

  /deep/ .ql-disabled {
    background-color: #F5F7FA;
    border-color: #E4E7ED;
    color: #C0C4CC;
    cursor: not-allowed;
  }

  /*.edit_container {*/
  /*  position: relative;*/
  /*}*/
</style>

toolbarOptions.js

const toolbarOptions = [
  // ['bold', 'italic', 'underline', 'strike'],
  ['blockquote', 'code-block'],
  [{'header': 1}, {'header': 2}],
  // [{'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': []}],
  // ['link', 'image', 'video'],
  ['clean']
]
export default toolbarOptions
// 只能粘贴原文本
      handleCustomMatcher(node, Delta) {
        let ops = []
        Delta.ops.forEach(op => {
          if (op.insert && typeof op.insert === 'string') {
            // 如果粘贴了图片,这里会是一个对象,所以可以这样处理
            ops.push({
              insert: op.insert
            })
          }
        })
        Delta.ops = ops
        return Delta
      },

拓展

npm install quill-image-resize-module quill-image-drop-module --save
// 引入
import { ImageDrop } from 'quill-image-drop-module'
import ImageResize from 'quill-image-resize-module'
Quill.register('modules/imageDrop', ImageDrop)
Quill.register('modules/imageResize', ImageResize)
// build/webpack.base.conf.js文件
const webpack = require('webpack')
plugins: [
   new webpack.ProvidePlugin({
       'window.Quill': 'quill/dist/quill.js',
       'Quill': 'quill/dist/quill.js'
 })
]
// 放在editorOption里面
 history: {
              delay: 1000,
              maxStack: 50,
              userOnly: false
            },
            imageDrop: true,
            imageResize: {
              displayStyles: {
                backgroundColor: 'black',
                border: 'none',
                color: 'white'
              },
              modules: [ 'Resize', 'DisplaySize', 'Toolbar' ]
            }

兼容性问题

兼容IE10以上

本文地址:https://blog.csdn.net/xuxuan1997/article/details/109235929

相关标签: Vue