搞了三天1个通宵的问题-vue-quill-editor的组件复用问题

困扰笔者很多天的问题

一个vue页面,v-for 循环多个富文本编辑器组件,在上传图片时,无法唯一确定当前编辑器的实例,会造成传一张图片,所有编辑器内都显示或者只是第一个编辑器显示

解决方法

1. 方法一 支持图片上传(上传至服务器后,富文本中存入地址)

  • 借助 el-upload 组件完成上传
  • 自定义工具栏容器,给工具来容器增加 id 标识,用于标识哪个编辑器的工具栏发起的上传动作
  • 全局配置 /src/main.js
.....
// quillEditor
// 引入quill-editor编辑器
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)
import Quill from 'quill'
// 实现quill-editor编辑器图片上传到服务器的功能
import { ImageExtend } from 'quill-image-extend-module'
Quill.register('modules/ImageExtend', ImageExtend)
// 实现quill-editor编辑器拖拽上传图片
import { ImageDrop } from 'quill-image-drop-module'
Quill.register('modules/ImageDrop', ImageDrop)
// 实现quill-editor编辑器调整图片尺寸
import imageResize from 'quill-image-resize-module'
Quill.register('modules/imageResize', imageResize)
.....
.....
  • 配置 webpack ,vue.config.js 文件
  • .....
    
    var webpack = require('webpack')
    
    ....
    
    configureWebpack: {
      plugins: [
        new webpack.ProvidePlugin({
          'window.Quill': 'quill/dist/quill.js',
          'Quill': 'quill/dist/quill.js'
        })
      ]
    },

  • 自定义vue-quill-editor组件,/src/views/components/qeditor2.vue
  • <template>
      <div>
        <el-row>
          <!-- 创建工具栏容器 -->
          <div :id="'aa'+callbackParam">
            <!-- Add font size dropdown -->
            <select class="ql-size">
              <option value="small"></option>
              <!-- Note a missing, thus falsy value, is used to reset to default -->
              <option selected></option>
              <option value="large"></option>
              <option value="huge"></option>
            </select>
            <!-- Add a bold button -->
            <button class="ql-bold"></button>
            <!-- Add subscript and superscript buttons -->
            <button class="ql-script" value="sub"></button>
            <button class="ql-script" value="super"></button>
            <button class="ql-image" title="照片"></button>
            <!-- 图片上传组件辅助-->
            <el-upload class="avatar-uploader" :action="uploadUrl" name="file" :show-file-list="false" :on-success="uploadSuccess"/>
          </div>
          <!-- 创建quill容器 -->
          <div id="editor" ref="editor" >{{html}}</div>
        </el-row>
      </div>
    </template>
    <script>
    export default {
      name: 'qeditor2',
      props: {
        value: String,
        callbackParam: {
          type: [String, Number],
          default: ''
        }
      },
      data() {
        return {
          html: this.value,
          uploadUrl: process.env.VUE_APP_BASE_API + '/' + process.env.VUE_APP_GATEWAY_RULENGINE_URL + `/upload/file`,  // 服务器上传地址
          options: {
            theme: 'snow',
            modules: {
              ImageDrop: true,
              imageResize: {
                handleStyles: {
                  backgroundColor: 'black',
                  border: 'none',
                  color: 'white'
                  // other camelCase styles for size display
                },
                displayStyles: {
                  backgroundColor: 'black',
                  border: 'none',
                  color: 'white'
                },
                modules: ['Resize', 'DisplaySize', 'Toolbar']
              },
              toolbar: {
                container: '#aa' + this.callbackParam,
                handlers: {
                  image: this.handleImgUpload
                }
              }
            }
          }
        }
      },
      mounted() {
        this.init()
      },
      methods: {
        init() {
          let dom = this.$el.querySelector('#editor')
          this.quill = new Quill(dom, this.options)
          const _this = this
          this.quill.on('text-change', function(delta, oldDelta, source) {
            // 获取富文本组件实例
            _this.html = _this.$refs.editor.children[0].innerHTML
            _this.$emit("quillContentInput", _this.html, _this.callbackParam)
          })
          this.$emit("qeditorInstancesSet", this.callbackParam, this.quill)
          console.log("手动初始化quill实例,并调用父页面的回调函数,存储实例对象" + this.quill)
        },
        handleImgUpload(value) {
          if (value) {
            // 调用element的图片上传组件
            console.log("id=" + this.callbackParam + "的工具栏触发quill富文本触发图像上传")
            document.querySelector('#aa'+ this.callbackParam+' .avatar-uploader .el-upload  .el-upload__input').click()
          } else {
            this.quill.format('image', false)
          }
        },
        uploadSuccess(res) {
          // 获取富文本组件实例
          let quill = this.$emit("getQeditorInstance", this.callbackParam ).quill
          console.log("根据id=" + this.callbackParam + ",从父页面获取quill实例对象,quill=" + quill)
    
          // 如果上传成功
          if (res.code === 200 && res.data) {
            // 获取光标所在位置
            let length = quill.selection.savedRange.index
            // 插入图片,res为服务器返回的图片链接地址
            quill.insertEmbed(length, 'image', res.data)
            // 调整光标到最后
            quill.setSelection(length + 1)
          } else {
            // 提示信息,需引入Message
            this.$message.error('图片插入失败!')
          }
        }
      }
    }
    </script>

  • 父页面调用子组件,/src/views/test.vue
  • <template>
      <div>
        <div v-for="(banner,index) in bannerList" :key="index" >
          <keep-alive>
            <qeditor2 :value="choiceList[index].value" :callback-param="index"
                      @quillContentInput="optionQuillContent"
                      @qeditorInstancesSet="qeditorInstancesSet"
                      @getQeditorInstance="qeditorInstancesGet"></qeditor2>
          </keep-alive>
        </div>
      </div>
    </template>
    <script>
    import qeditor2 from './components/qeditor2'
    export default {
      name: "ueditor",
      components: {
        qeditor2
      },
      data() {
        return {
          bannerList: [1, 2],
          choiceList: [
            { value: '123' },
            { value: '456' }
          ],
          // 存放 quill 组件实例
          qeditorInstances: new Map()
        }
      },
      methods: {
        // 子组件富文本内容改变时的回调方法
        optionQuillContent(newVel, index) {
          this.choiceList[index] = newVel
          console.log('父节点收集富文本内容:' + this.choiceList)
        },
        qeditorInstancesSet(key, quillObj) {
          this.qeditorInstances.set(key, quillObj)
        },
        qeditorInstancesGet(key) {
          this.qeditorInstances.get(key)
        }
      }
    }
    </script>

    2. 方法二 支持图片上传(上传至服务器后,富文本中存入地址)

  • 使用 quill自带的 quill-image-extend-module 扩展,完成上传
  • 全局配置 /src/main.js
  • .....
    // quillEditor
    // 引入quill-editor编辑器
    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)
    import Quill from 'quill'
    // 实现quill-editor编辑器图片上传到服务器的功能
    import { ImageExtend } from 'quill-image-extend-module'
    Quill.register('modules/ImageExtend', ImageExtend)
    // 实现quill-editor编辑器拖拽上传图片
    import { ImageDrop } from 'quill-image-drop-module'
    Quill.register('modules/ImageDrop', ImageDrop)
    // 实现quill-editor编辑器调整图片尺寸
    import imageResize from 'quill-image-resize-module'
    Quill.register('modules/imageResize', imageResize)
    .....
    .....

  • 配置 webpack ,vue.config.js 文件
  • .....
    
    var webpack = require('webpack')
    
    ....
    
    configureWebpack: {
      plugins: [
        new webpack.ProvidePlugin({
          'window.Quill': 'quill/dist/quill.js',
          'Quill': 'quill/dist/quill.js'
        })
      ]
    },

  • 自定义vue-quill-editor组件,/src/views/components/qeditor3.vue
  • <template>
      <div>
        <el-row>
          <div class="quill-wrap">
            <quill-editor
              v-model="html"
              ref="myQuillEditor"
              :options="options"
              @blur="onEditorBlur($event)"
              @focus="onEditorFocus($event)"
              @ready="onEditorReady($event)">
            >
            </quill-editor>
          </div>
        </el-row>
      </div>
    </template>
    <script>
    import { container, QuillWatch } from 'quill-image-extend-module'
    export default {
      name: 'qeditor3',
      props: {
        value: {
          type: [Number, Object, Array, String],
          default: ''
        },
        callbackParam: {
          type: [Number, Object, Array, String],
          default: ''
        },
      },
      data() {
        return {
          html: this.value,
          options: {
            theme: 'snow',
            modules: {
              ImageDrop: true,
              imageResize: {
                handleStyles: {
                  backgroundColor: 'black',
                  border: 'none',
                  color: 'white'
                  // other camelCase styles for size display
                },
                displayStyles: {
                  backgroundColor: 'black',
                  border: 'none',
                  color: 'white'
                },
                modules: ['Resize', 'DisplaySize', 'Toolbar']
              },
              ImageExtend: {
                loading: true,
                name: 'file',
                action: process.env.VUE_APP_BASE_API + '/' + process.env.VUE_APP_GATEWAY_RULENGINE_URL + `/upload/file`,
                response: (res) => {
                  debugger
                  return res.data
                }
              },
              toolbar: {
                container: container,
                handlers: {
                  'image': function() {
                    QuillWatch.emit(this.quill.id)
                  }
                }
              }
            }
          }
        }
      },
      methods: {
        // 失去焦点
        onEditorBlur(quill) {
          this.$emit("quillContentInput", this.html, this.callbackParam)
          console.log('editor blur!', quill)
        },
        // 光标进入编辑器
        onEditorFocus(quill) {
          console.log('editor focus!', quill)
        },
        onEditorReady(quill) {
          console.log('editor ready!', quill)
        }
      },
      computed: {
        editor() {
          return this.$refs.myQuillEditor.quill
        }
      },
      mounted() {
        console.log('this is current quill instance object', this.editor)
      }
    }
    </script>

 

  • 父页面调用子组件,/src/views/test.vue

<template>
  <div>
    <div v-for="(banner,index) in bannerList" :key="index" >
      <keep-alive>
        <qeditor3 :value="choiceList[index].value" :callback-param="index" @quillContentInput="optionQuillContent" ></qeditor3>
      </keep-alive>
    </div>
  </div>
</template>
<script>
import qeditor3 from './components/qeditor3'
export default {
  name: "ueditor",
  components: {
    qeditor3
  },
  data() {
    return {
      bannerList: [1, 2],
      choiceList: [
        { value: '123' },
        { value: '456' }
      ]
    }
  },
  methods: {
    // 子组件富文本内容改变时的回调方法
    optionQuillContent(newVel, index) {
      this.choiceList[index] = newVel
      console.log('父节点收集富文本内容:' + this.choiceList)
    }
  }
}
</script>

 

两种方法亲测都有效,官方推荐使用第二种方式

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绿竹痕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值