其他分享
首页 > 其他分享> > vue-quill-editor 自定义 img 标签,给标签添加 href 属性

vue-quill-editor 自定义 img 标签,给标签添加 href 属性

作者:互联网

vue-quill-editor 自定义 img 标签,给标签添加 href 属性

需求:上传图片成功之后,给图片标签插入 href 属性,内容为自定义的一段字符串,格式大概如下:<img src="xxxxx" href="abcdefg"/>

传统插入图片方法是图片上传到服务器成功之后,在编辑器里插入图片,传入图片url,如下:

    uploadSuccess (res) {
      // 获取富文本组件实例
      let quill = this.$refs.QuillEditor.quill
      // 如果上传成功
      if (res) {
        // 获取光标所在位置
        let length = quill.getSelection().index;
        // 插入图片,res为服务器返回的图片链接地址
        quill.insertEmbed(length, 'image', res.result[0].url)
        // 调整光标到最后
        quill.setSelection(length + 1)
      } else {
        // 提示信息,需引入Message
        this.$message.error('图片插入失败!')
      }
    }

这里需要给 img 标签添加 href 属性,所以,就想着使用插入节点的方式去实现:

    uploadSuccess (res) {
      // 获取富文本组件实例
      let quill = this.$refs.QuillEditor.quill
      // 如果上传成功
      if (res) {
        let imgUrl = res.result[0].url
        let obj = 'abcdefg'
        let selection = window.getSelection(true)
        // getRangeAt(index):返回一个包含当前选区内容的区域对象。
        let range = selection.getRangeAt(0)
        let insertNode = document.createElement('img')
        // 设置标签属性
        insertNode.setAttribute('src', imgUrl)
        insertNode.setAttribute('href', obj)
        quill.setSelection(quill.selection.savedRange.index + 1)  // 这个方法可以获取光标位置
        // setStart(startNode, startOffset):用于设置 Range的开始位置
        // startNode 用于设定 Range的起始位置
        // startOffset 必须为不小于0的整数,表示从startNode的开始位置算起的偏移量
        range.setStart(range.endContainer, range.endOffset)
        // insertNode():用来在选区的开头插入节点
        range.insertNode(insertNode)
        // setEnd(endNode, endOffset):用于设置 Range的结束位置
        // endNode 用于设定 Range的结束位置
        // endOffset 必须为不小于0的整数,表示从endNode的结束位置算起的偏移量
        // Range.endContainer 是一个只读属性。它会返回Range对象结束的Node。如果要改变一个节点结束的位置
        range.setEnd(range.endContainer, range.endOffset)
        selection.collapse(range.endContainer, range.endOffset) // 合并范围至末尾
      } else {
        // 提示信息,需引入Message
        this.$message.error('图片插入失败!')
      }
    }

可以看到,在插入图片后,图片标签上面有一个 href 属性,效果如下:
在这里插入图片描述

但是,后面发现一个问题:保存数据之后,再进行编辑,编辑器中回显的图片上自定义的 href 属性丢失了,如下:
在这里插入图片描述
这样就有问题了,再次保存这条数据的话,图片上自定义的 href 属性丢失,图片的数据就不是想要的了。

于是,只好又去找别的方法,发现要自定义 image 标签,实践了下,确实能解决上面的问题。

具体实现:

(1)引入插件,将上传图片的配置项进行重写,将新配置好的类进行注册:

//引入Qill插件
import Quill from "quill";
let BlockEmbed = Quill.imports['blots/embed'];
// 自定义img标签
class ImageBlot extends BlockEmbed {
  static create (value) {
    let node = super.create();
    node.setAttribute('src', value.src);
    node.setAttribute('href', value.href);
    return node;
  }
  static value (node) {
    return {
      src: node.getAttribute('src'),
      href: node.getAttribute('href')
    }
  }
}
ImageBlot.blotName = 'image';
ImageBlot.tagName = 'img';
Quill.register(ImageBlot)

(2)在上传成功的回调中写入图片:

    uploadSuccess (res) {
      // 获取富文本组件实例
      let quill = this.$refs.QuillEditor.quill
      // 如果上传成功
      if (res) {
        // 获取富文本组件实例
        let quill = this.$refs.QuillEditor.quill
        // 获取光标所在位置
        let range = quill.getSelection(true)
        let imgUrl = res.result[0].url
        // 插入 href 内容
        let obj = 'abcdefg'
        quill.insertEmbed(range.index, 'image', { src: imgUrl, href: obj })
        let location = quill.getLength()
        quill.setSelection(location + 1)
      } else {
        // 提示信息,需引入Message
        this.$message.error('图片插入失败!')
      }
    }

插入一张图片试试,可以看到,标签上有 href 属性:
在这里插入图片描述

这种方法插入的图片标签,再次编辑,属性数据不会丢失。

完整版代码:

<template>
  <div class="quill-editor">
    <!-- 图片上传组件辅助-->
    <el-upload class="avatar-uploader" :action="uploadUrl" name="img" :show-file-list="false" :on-success="uploadSuccess" :before-upload="beforeUpload">
    </el-upload>
    <!--富文本编辑器组件-->
    <quill-editor v-model="content" :content="content" :options="editorOption" @blur="onEditorBlur($event)" @focus="onEditorFocus($event)" @ready="onEditorReady($event)" ref="QuillEditor">
    </quill-editor>
    <div v-html="content" />
  </div>
</template>

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

//引入Qill插件
import Quill from "quill";
let BlockEmbed = Quill.imports['blots/embed'];
// 自定义img标签
class ImageBlot extends BlockEmbed {
  static create (value) {
    let node = super.create();
    node.setAttribute('src', value.src);
    node.setAttribute('href', value.href);
    return node;
  }
  static value (node) {
    return {
      src: node.getAttribute('src'),
      href: node.getAttribute('href')
    }
  }
}
ImageBlot.blotName = 'image';
ImageBlot.tagName = 'img';
Quill.register(ImageBlot)

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': ['SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong', 'Arial'] }],// 字体
  [{ 'align': [] }], // 居中
  ['clean'],                                       // 清除样式,
  ['link', 'image'],  // 上传图片、上传视频
]
export default {
  components: {
    quillEditor
  },
  data () {
    return {
      name: 'register-modules-example',
      content: '',
      editorOption: {
        placeholder: '请在这里输入',
        theme: 'snow', //主题 snow/bubble
        modules: {
          history: {
            delay: 1000,
            maxStack: 50,
            userOnly: false
          },
          toolbar: {
            container: toolbarOptions,
            handlers: {
              image: function (value) {
                if (value) {
                  // 调用element的图片上传组件
                  document.querySelector('.avatar-uploader input').click()
                } else {
                  this.quill.format('image', false)
                }
              }
            }
          }
        }
      },
      uploadUrl: `XXXXXXXX`  // 服务器上传地址
    }
  },
  methods: {
    // 失去焦点
    onEditorBlur (editor) { },
    // 获得焦点
    onEditorFocus (editor) { },
    // 开始
    onEditorReady (editor) { },
    // 值发生变化
    onEditorChange (editor) {
      this.content = editor.html;
      console.log(editor);
    },
    beforeUpload (file) { },
    uploadSuccess (res) {
      // 获取富文本组件实例
      let quill = this.$refs.QuillEditor.quill
      // 如果上传成功
      if (res) {
        // 获取富文本组件实例
        let quill = this.$refs.QuillEditor.quill
        // 获取光标所在位置
        let range = quill.getSelection(true)
        let imgUrl = res.result[0].url
        // 插入 href 内容
        let obj = 'abcdefg'
        quill.insertEmbed(range.index, 'image', { src: imgUrl, href: obj })
        let location = quill.getLength()
        quill.setSelection(location + 1)
      } else {
        // 提示信息,需引入Message
        this.$message.error('图片插入失败!')
      }
    }
  }
}
</script>

标签:node,vue,自定义,标签,range,href,let,res,quill
来源: https://blog.csdn.net/HH18700418030/article/details/120077090