vue中组件如何使用vue-quill-editor

 更新时间:2024年01月16日 08:48:51   作者:是文静的  
这篇文章主要介绍了vue中组件如何使用vue-quill-editor问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、使用vue-quill-editor富文本组件

1.下载依赖

yarn add vue-quill-editor
yarn add quill

2.组件文件结构

Editor文件夹下Editor.vue

<template>
  <div class="edit_container">
    <!--  新增时输入 -->
    <quill-editor
      v-model="content"
      ref="myQuillEditor"
      :options="editorOption"
      @blur="onEditorBlur($event)"
      @focus="onEditorFocus($event)"
      @change="onEditorChange($event)"
    >
    </quill-editor>
    <!-- 从数据库读取展示 -->
    <div v-html="str" class="ql-editor">
      {{ str }}
    </div>
  </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'

export default {
  name: 'Editor',
  components: {
    quillEditor
  },
  data () {
    return {
      content: ``,
      editorOption: {
        placeholder: '请在这里输入',
        modules: {
          toolbar: [
            ['bold', 'italic', 'underline', 'strike'], // 加粗,斜体,下划线,删除线
            ['blockquote', 'code-block'], // 引用,代码块
            [{ 'header': 1 }, { 'header': 2 }], // 标题,键值对的形式;1、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': [false, 'heiti', 'songti', 'kaiti', 'lishu', 'arial', 'monospace'] }], // 字体
            [{ 'align': [] }], // 对齐方式
            ['clean'], // 清除字体样式
            ['image', 'video'] // 上传图片、上传视频
          ]
        }
      }
    }
  },
  computed: {
    // 当前富文本实例
    editor () {
      return this.$refs.myQuillEditor.quill
    }
  },
  mounted () {
    const content = ''// 请求后台返回的内容字符串
    this.str = this.escapeStringHTML(content)
  },
  methods: {
    onEditorReady (editor) { // 准备编辑器
    },
    onEditorBlur () {}, // 失去焦点事件
    onEditorFocus () {}, // 获得焦点事件
    onEditorChange () {
      this.$emit('change', this.escapeStringHTML(this.content))
    }, // 内容改变事件
    // 转码
    escapeStringHTML (str) {
      str = str.replace(/</g, '<')
      str = str.replace(/>/g, '>')
      return str
    }
  }
}
</script>
<style>
.editor {
  line-height: normal !important;
  height: 500px;
}
.ql-snow .ql-tooltip[data-mode=link]::before {
  content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
    border-right: 0px;
    content: '保存';
    padding-right: 0px;
}

.ql-snow .ql-tooltip[data-mode=video]::before {
    content: "请输入视频地址:";
}

.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
  content: '14px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
  content: '10px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
  content: '18px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
  content: '32px';
}

.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
  content: '文本';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
  content: '标题1';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
  content: '标题2';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
  content: '标题3';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
  content: '标题4';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
  content: '标题5';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
  content: '标题6';
}

.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
  content: '标准字体';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {
  content: '衬线字体';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {
  content: '等宽字体';
}
</style>

Editor文件夹下index.js

import Editor from './Editor'

export default Editor

components文件夹下index.js

import Editor from '@/components/Editor'
export {
  Editor
}

3.使用

<template>
  <div>
    <Editor class="CKEditor" ref="Editor" v-model="content" @change="callbackChangeEditor"></Editor>
  </div>
</template>
<script>
import { Editor } from '@/components'
  export default {
    components: {
      Editor
    },
    data () {
      return {
        content: '',
      }
    },
    mounted () {},
    methods: {
      callbackChangeEditor (value) {
        this.content = value
      },
    }
  }
</script>
<style lang="less" scoped>
</style>

二、此时上传的图片为base64格式,我们需要上传图片

下载依赖

yarn add quill-image-extend-module
<template>
  <div class="edit_container">
    <!--  新增时输入 -->
    <quill-editor
      v-model="content"
      ref="myQuillEditor"
      :options="editorOption"
      @blur="onEditorBlur($event)"
      @focus="onEditorFocus($event)"
      @change="onEditorChange($event)"
    >
    </quill-editor>
  </div>
</template>
<script>
import Vue from 'vue'
import {
  ACCESS_TOKEN
} from '@/store/mutation-types'
import { quillEditor, Quill } from 'vue-quill-editor' // 调用编辑器
import { container, ImageExtend, QuillWatch } from 'quill-image-extend-module'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
Quill.register('modules/ImageExtend', ImageExtend)

export default {
  name: 'RichTextEditor',
  components: {
    quillEditor
  },
  props: {
    fileUrl: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      content: ``,
      editorOption: {
        placeholder: '请在这里输入',
        modules: {
          ImageExtend: {
            loading: true,
            name: 'fileData',
            // 更多配置见官方文档https://www.kancloud.cn/liuwave/quill/1434141
            // 设置请求头部
            headers: (xhr) => {
              xhr.setRequestHeader('Authorization', Vue.ls.get(ACCESS_TOKEN))
            },
            action: this.fileUrl, // 这里写入请求后台地址 例如:"http://xxx.xxx.xxx.xxx:xxx/api/file/upload/indexFile",
            response: (res) => {
              return res.url // 这里写入请求返回的数据,也就是一个图片字符串
            }
          },
          toolbar: {
            container: container,
            handlers: {
              'image': function () {
                QuillWatch.emit(this.quill.id)
              }
            }
          }
        }
      }
    }
  },
  computed: {
    // 当前富文本实例
    editor () {
      return this.$refs.myQuillEditor.quill
    }
  },
  mounted () {
  },
  methods: {
    onEditorReady (editor) { // 准备编辑器
    },
    onEditorBlur () {}, // 失去焦点事件
    onEditorFocus () {}, // 获得焦点事件
    onEditorChange () {
      this.$emit('change', this.escapeStringHTML(this.content))
    }, // 内容改变事件
    // 转码
    escapeStringHTML (str) {
      str = str.replace(/</g, '<')
      str = str.replace(/>/g, '>')
      return str
    }
  }
}
</script>
<style>
img{
  max-width: 100% !important;
  height: auto !important;
}
.editor {
  line-height: normal !important;
  height: 500px;
}
.ql-container{
  height: 500px;
}
.ql-snow .ql-tooltip[data-mode=link]::before {
  content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
    border-right: 0px;
    content: '保存';
    padding-right: 0px;
}

.ql-snow .ql-tooltip[data-mode=video]::before {
    content: "请输入视频地址:";
}

.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
  content: '14px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
  content: '10px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
  content: '18px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
  content: '32px';
}

.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
  content: '文本';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
  content: '标题1';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
  content: '标题2';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
  content: '标题3';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
  content: '标题4';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
  content: '标题5';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
  content: '标题6';
}

.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
  content: '标准字体';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {
  content: '衬线字体';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {
  content: '等宽字体';
}
</style>

使用

<template>
  <div>
    <Editor class="CKEditor" ref="Editor" v-model="content" @change="callbackChangeEditor" :fileUrl="richTextFileUrl"></Editor>
  </div>
</template>
<script>
import { Editor } from '@/components'
  export default {
    components: {
      Editor
    },
    data () {
      return {
        content: '',
        // 图片上传url的方法
        richTextFileUrl: getWorkOrderUrl(), // http://localhost:8088/api/v1/insideWorkOrder/upload
      }
    },
    mounted () {},
    methods: {
      callbackChangeEditor (value) {
        this.content = value
      },
    }
  }
</script>
<style lang="less" scoped>
</style>

三、图片过大想要拖拽图片改变大小问题

下载依赖

yarn add quill-image-drop-module
yarn add quill-image-resize-module

在组件里引入使用

import resizeImage from 'quill-image-resize-module' // 图片缩放组件引用
import { ImageDrop } from 'quill-image-drop-module'
Quill.register('modules/imageDrop', ImageDrop) // 注册
Quill.register('modules/resizeImage ', resizeImage)

设置editorOption对象

editorOption: {
  placeholder: '请在这里输入',
  modules: {
    ImageExtend: {
      loading: true,
      name: 'fileData',
      headers: (xhr) => {
        xhr.setRequestHeader('Authorization', Vue.ls.get(ACCESS_TOKEN))
      },
      action: this.fileUrl, // 这里写入请求后台地址 例如:"http://xxx.xxx.xxx.xxx:xxx/api/file/upload/indexFile",
      response: (res) => {
        return res.url // 这里写入请求返回的数据,也就是一个图片字符串
      }
    },
    imageDrop: true, // 图片拖拽
    imageResize: { // 放大缩小
      displayStyles: {
        backgroundColor: 'black',
        border: 'none',
        color: 'white'
      },
      modules: ['Resize', 'DisplaySize', 'Toolbar']
    },
    toolbar: {
      container: container,
      handlers: {
        'image': function () {
          QuillWatch.emit(this.quill.id)
        }
      }
    }
  }
}

此时浏览器会显示以下报错

1.找到项目的build/webpack.base.conf.js文件添加如下代码:

var webpack = require('webpack');
module.exports = {
configureWebpack: {
    plugins: [
     ...
      new webpack.ProvidePlugin({
        'window.Quill': 'quill/dist/quill.js',
        'Quill': 'quill/dist/quill.js'
      })
      ...
    ]
  }
}

2.找到根目录下的vue.config.js文件在configureWebpack下修改

const webpack = require('webpack')
module.exports = {
  configureWebpack: {
    plugins: [
      new webpack.ProvidePlugin({
        'window.Quill': 'quill/dist/quill.js',
        Quill: 'quill/dist/quill.js'
      })
    ]
  }
}

按照已有方式添加在configureWebpack下

config.plugins.push(
  new webpack.ProvidePlugin({
    'window.Quill': 'quill/dist/quill.js',
    Quill: 'quill/dist/quill.js'
  })
)

最后重启项目

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue自定义键盘信息、监听数据变化的方法示例【基于vm.$watch】

    vue自定义键盘信息、监听数据变化的方法示例【基于vm.$watch】

    这篇文章主要介绍了vue自定义键盘信息、监听数据变化的方法,结合实例形式分析了vue.js基于vm.$watch进行事件监听相关操作技巧,需要的朋友可以参考下
    2019-03-03
  • vuex5中的Pinia插件机制

    vuex5中的Pinia插件机制

    这篇文章主要介绍了vuex5中的Pinia插件机制,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • 解决vue-cli 配置资源引用的绝对路径问题

    解决vue-cli 配置资源引用的绝对路径问题

    这篇文章主要介绍了vue-cli 配置资源引用的绝对路径的问题,本文通过图文实例相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • vue双向数据绑定指令v-model的用法

    vue双向数据绑定指令v-model的用法

    这篇文章主要介绍了vue双向数据绑定指令v-model的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • vue中@click绑定事件点击不生效的解决

    vue中@click绑定事件点击不生效的解决

    这篇文章主要介绍了vue中@click绑定事件点击不生效的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Vue页面内公共的多类型附件图片上传区域并适用折叠面板(示例代码)

    Vue页面内公共的多类型附件图片上传区域并适用折叠面板(示例代码)

    本文中实现的附件上传区域支持超多类型附件分类型上传,并且可根据特定条件具体展示某些类型的附件上传,本文给大家分享Vue页面内公共的多类型附件图片上传区域并适用折叠面板的示例代码,需要的朋友参考下吧
    2021-12-12
  • 在Vue中配置代理服务器的方法详解

    在Vue中配置代理服务器的方法详解

    这篇文章主要给大家介绍了关于如何在Vue中配置代理服务器的相关资料,文中通过图文以及示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-12-12
  • 详解Vue中子组件修改父组件传过来的值的三种方式

    详解Vue中子组件修改父组件传过来的值的三种方式

    这篇文章主要为大家详细介绍了Vue中子组件修改父组件传过来的值的三种方式,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下
    2024-12-12
  • Vue表单验证插件的制作过程

    Vue表单验证插件的制作过程

    这篇文章主要为大家详细介绍了Vue表单验证插件的制作过程,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • 利用Vue模拟实现element-ui的分页器效果

    利用Vue模拟实现element-ui的分页器效果

    这篇文章主要为大家详细介绍了如何利用Vue模拟实现element-ui的分页器效果,文中的示例代码讲解详细,感兴趣的小伙伴可以动手尝试一下
    2022-11-11

最新评论