vue quill-editor富文本自定义工具栏组件封装、自定义行高字体大小、图片放大缩小、图片上传

Quilleditor.vue

<template>
  <div id="Quill" class="ql-editor">
    <quill-editor
            v-model="content"
            ref="myQuillEditor"
            @blur="onEditorBlur($event)"
            @focus="onEditorFocus($event)"
            @change="onEditorChange($event)"
            :options="editorOption"
    >
      <!-- 自定义toolar -->
      <div id="toolbar" slot="toolbar">
        <!-- Add a bold button -->
        <button class="ql-bold" title="加粗">Bold</button>
        <button class="ql-italic" title="斜体">Italic</button>
        <button class="ql-underline" title="下划线">underline</button>
        <button class="ql-strike" title="删除线">strike</button>
        <button class="ql-blockquote" title="引用"></button>
        <button class="ql-code-block" title="代码"></button>
        <button class="ql-header" value="1" title="标题1"></button>
        <button class="ql-header" value="2" title="标题2"></button>
        <!--Add list -->
        <button class="ql-list" value="ordered" title="有序列表"></button>
        <button class="ql-list" value="bullet" title="无序列表"></button>
        <!-- Add font size dropdown -->
        <select
                class="ql-header"
                title="段落格式"
                style="line-height: initial;"
        >
          <option selected>段落</option>
          <option value="1">标题1</option>
          <option value="2">标题2</option>
          <option value="3">标题3</option>
          <option value="4">标题4</option>
          <option value="5">标题5</option>
          <option value="6">标题6</option>
        </select>
        <select
                class="ql-size fontSize"
                title="字体大小"
                style="line-height: initial;"
        >
          <option
                  v-for="item in fontSizeArr"
                  :value="item.value"
                  :key="item.value"
          >{{ item.value }}</option
          >
        </select>
        <select class="ql-font" title="字体" style="line-height: initial;">
          <option value="SimSun">宋体</option>
          <option value="SimHei">黑体</option>
          <option value="Microsoft-YaHei">微软雅黑</option>
          <option value="KaiTi">楷体</option>
          <option value="FangSong">仿宋</option>
          <option value="Arial">Arial</option>
        </select>
        <!-- Add subscript and superscript buttons -->
        <select class="ql-color" value="color" title="字体颜色"></select>
        <select
                class="ql-background"
                value="background"
                title="背景颜色"
        ></select>
        <select class="ql-align" value="align" title="对齐"></select>
        <select class="ql-lineHeight">
          <option
                  v-for="(item, index) in lineHeight"
                  :key="index"
                  :value="item"
                  :selected="index === 0"
          >{{ item }}</option
          >
        </select>
        <!-- <select title="文字行高" class="ql-line-height">
    <option selected></option>
    <option value="1">a</option>
</select> -->
        <button
                id="custom-button"
                @click.prevent="videoHandler"
                title="图片"
                style="margin: 0 0 0 49px;"
        >
          <span></span>
        </button>
        <!-- <button id="custom-button" @click.prevent="videoHandler" title="视频">
                  <Icon type="md-play" />
        </button>-->

        <button class="ql-clean" title="还原"></button>

        <!-- You can also add your own -->
      </div>
    </quill-editor>
    <!-- <div class="limit">
          当前已输入 <span>{{ nowLength }}</span> 个字符,您还可以输入
          <span>{{ SurplusLength }}</span> 个字符。
        </div>
          :action="'/api/manage/ueditor/ueditorVideo'"
    -->
    <Upload
            :action="$HTTPURL + this.uploadUrl"
            :before-upload="beforeUpload"
            :data="uploadData"
            :on-success="uploadSuccess"
            style="display:none"
            ref="upload"
    >
      <Button icon="ios-cloud-upload-outline" id="imgInput">点击上传</Button>
    </Upload>
  </div>
</template>

<script>
  import { quillRedefine } from "vue-quill-editor-upload";
  import VueQuillEditor, { Quill } from "vue-quill-editor";
  import { ImageDrop } from "quill-image-drop-module";
  import ImageResize from "quill-image-resize-module";
  import Parchment from 'parchment';
  import lineHeight from './lineHeight';

  Quill.register("modules/imageDrop", ImageDrop);
  Quill.register("modules/imageResize", ImageResize);

  let fontSizeStyle = Quill.import("attributors/style/size");
  fontSizeStyle.whitelist = [
    "16px",
    "12px",
    "14px",
    "18px",
    "20px",
    "22px",
    "24px",
    "26px",
    "28px",
    "30px",
    "32px",
    "34px",
    "36px",
    "38px",
    "40px"
  ];
  Quill.register(fontSizeStyle, true);

  export default {
    name: "Quilleditor",
    props: {
      formData: {
        type: Object,
        default: () => {
          return {};
        }
      }
    },
    data() {
      return {
        lineHeight: ['1', '1.1','1.2','1.3','1.4','1.5','1.6','1.7','1.8','1.9','2','2.1','2.2','2.3','2.4','2.5','2.6','2.7','2.8','2.9','3'],
        fontSizeArr: [
          { value: "16px" },
          { value: "12px" },
          { value: "14px" },
          { value: "18px" },
          { value: "20px" },
          { value: "22px" },
          { value: "24px" },
          { value: "26px" },
          { value: "28px" },
          { value: "30px" },
          { value: "32px" },
          { value: "34px" },
          { value: "36px" },
          { value: "38px" },
          { value: "40px" }
        ],
        content: "",
        editorOption: {},
        uploadUrl: "/ueditor/ueditorImage",
        uploadData: {
          tableType: ""
        },

        // 上传七牛的actiond地址
        get qnLocation() {
          return "/api/manage/housesMain/uploadVideo";
        }
      };
    },
    created() {
      this.editorOption = quillRedefine({
        // 图片上传的设置
        uploadConfig: {
          action: this.$HTTPURL + this.uploadUrl,
          // 必填参数 图片上传地址
          // 必选参数  res是一个函数,函数接收的response为上传成功时服务器返回的数据
          // 你必须把返回的数据中所包含的图片地址 return 回去
          res: respnse => {
            return respnse.data.originalImagePath;
          },
          methods: "POST", // 可选参数 图片上传方式  默认为post // 可选参数 如果需要token验证,假设你的token有存放在sessionStorage
          /* token: sessionStorage.token,*/ name: "file", // 可选参数 文件的参数名 默认为img // 可选参数   图片限制大小,单位为Kb, 1M = 1024Kb
          /*  size: 500,*/ accept:
                  "image/png, image/gif, image/jpeg, image/bmp, image/x-icon", // 可选参数 可上传的图片格式
          // input点击事件  formData是提交的表单实体
          // 图片上传参数名
          change: formData => {},
          // 设置请求头 xhr: 异步请求, formData: 表单对象
          header: (xhr, formData) => {
            // xhr.setRequestHeader('myHeader','myValue');
            formData.append("imageType", this.formData.contentImage);
            formData.append("tableType", this.formData.tableType);
            formData.append("action", this.formData.action);
          },
          // start: function (){}
          start: () => {}, // 可选参数 接收一个函数 开始上传数据时会触发
          end: () => {}, // 可选参数 接收一个函数 上传数据完成(成功或者失败)时会触发
          success: () => {}, // 可选参数 接收一个函数 上传数据成功时会触发
          error: () => {} // 可选参数 接收一个函数 上传数据中断时会触发
        },
        // 以下所有设置都和vue-quill-editor本身所对应
        modules: {
          toolbar: [], //工具菜单栏配置
          handlers: {
            image: function(value) {
              if (value) {
                // 触发input框选择图片文件
                document.querySelector(".avatar-uploader input").click();
              } else {
                this.quill.format("image", false);
              }
            },
            video: function(val) {
              document.querySelector("#upvideoshow").click();
            }
          }
        },
        placeholder: "请在这里添加描述", //提示
        readyOnly: false, //是否只读
        theme: "snow", //主题 snow/bubble
        syntax: true //语法检测
      });
      this.editorOption.modules.history = {
        delay: 1000,
        maxStack: 50,
        userOnly: false
      };
      this.editorOption.modules.imageDrop = true;
      this.editorOption.modules.toolbar = {
        container: "#toolbar"
      };
      this.editorOption.modules.imageResize = {
        displayStyles: {
          backgroundColor: "black",
          border: "none",
          color: "white"
        },
        modules: ["Resize", "DisplaySize", "Toolbar"]
      };
      // this.uploadData.tableType = this.formData.tableType;
      this.uploadData = this.formData;
    },
    computed: {
      editor() {
        return this.$refs.myQuillEditor.quill;
      }
    },
    watch: {
      content(newVal, oldVal) {
        if (newVal) {
          this.content = newVal;
        } else if (!newVal) {
          this.content = "";
        }
      }
    },
    methods: {
      onEditorReady(editor) {
        // 准备编辑器
      },
      onEditorBlur() {}, // 失去焦点事件
      onEditorFocus(val) {
        // 富文本获得焦点时的事件
      },
      /**
       * @description [onEditorChange 输入文本改变事件]
       * @param {Object} editor 返回的编辑对象{html, text, quill}
       * @return   {null}   [没有返回]
       */
      onEditorChange(editor) {
        //   console.log(editor);
        this.content = editor.html;
        this.$emit("content", this.content);
      }, // 内容改变事件

      // 富文本图片上传前
      beforeUpload() {
        // 显示loading动画
        this.quillUpdateImg = true;
      },

      uploadSuccess(e, res, file) {
        // 获取富文本组件实例
        let quill = this.editor;
        let _self = this;
        // 如果上传成功
        if (res.response.status === 0) {
          _self.addRange = _self.$refs.myQuillEditor.quill.getSelection();
          let length = _self.$refs.myQuillEditor.quill.selection.savedRange.index;
          // 插入图片  res为服务器返回的图片地址
          quill.insertEmbed(
                  _self.addRange !== null ? _self.addRange.index : 0,
                  "image",
                  res.response.data.originalImagePath,
                  Quill.sources
          );
          // 调整光标到最后
          quill.setSelection(length + 1);
        } else {
          this.$Message.error("图片插入失败");
        }
        // loading动画消失
        this.quillUpdateImg = false;
      },

      // 富文本图片上传失败
      uploadError() {
        // loading动画消失
        this.quillUpdateImg = false;
        this.$message.error("图片插入失败");
      },

      // 图片上传成功回调   插入到编辑器中
      upScuccess(e, file, fileList) {
        this.fullscreenLoading = false;
        let vm = this;
        let url = "";
        url = e.data.originalVideo;
        if (url != null && url.length > 0) {
          // 将文件上传后的URL地址插入到编辑器文本中
          let value = url;
          vm.addRange = vm.$refs.myQuillEditor.quill.getSelection();
          value = value.indexOf("http") !== -1 ? value : "http:" + value;
          vm.$refs.myQuillEditor.quill.insertEmbed(
                  vm.addRange !== null ? vm.addRange.index : 0,
                  vm.uploadType,
                  value,
                  Quill.sources
          ); // 调用编辑器的 insertEmbed 方法,插入URL
        } else {
        }
        this.$refs["upload"].clearFiles(); // 插入成功后清除input的内容
      },
      // 点击视频ICON触发事件
      videoHandler() {
        // this.addRange = this.$refs.myQuillEditor.quill.getSelection();
        // if (state) {
        let fileInput = document.getElementById("imgInput");
        fileInput.click(); // 加一个触发事件
        // 加一个触发事件
        // }
        // this.uploadType = "video";
      }
    },
    // 页面加载后执行 为编辑器的图片图标和视频图标绑定点击事件
    mounted() {
      Quill.register("formats/lineHeight", lineHeight, true);
    }
  };
</script>
<style lang="scss">
  @import "Quilleditor";
</style>

Quilleditor.scss

#Quill {
  .quill-editor .ql-size .ql-picker-options {
    height: 200px;
    overflow: auto;
  }

  .ql-container {
    min-height: 350px;
    font-size: 16px;
    line-height: 1.4;
  }

  /** 设置行高 */

  .ql-toolbar {
    text-align: left;
  }

  .ql-lineHeight {
    margin: 6px 0 0 0;

    .ql-picker-options {
      height: 200px;
      overflow: auto;
    }
  }

  .ql-lineHeight::before {
    content: "行高:";
    position: relative;
    top: -2px;
    left: 8px;
  }

  .ql-lineHeight .ql-picker-label {
    left: 50px;
    top: -25px;
  }

  .ql-lineHeight .ql-picker-options {
    left: 50px;
  }

  .ql-picker.ql-lineHeight .ql-picker-label[data-value='1']::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value='1']::before {
    content: "1.0";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.1"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.1"]::before {
    content: "1.1";
  }

  .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.2"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.2"]::before {
    content: "1.2";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.3"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.3"]::before {
    content: "1.3";
  }

  .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.4"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.4"]::before {
    content: "1.4";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.5"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.5"]::before {
    content: "1.5";
  }

  .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.6"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.6"]::before {
    content: "1.6";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.7"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.7"]::before {
    content: "1.7";
  }

  .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.8"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.8"]::before {
    content: "1.8";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="1.9"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="1.9"]::before {
    content: "1.9";
  }

  .ql-picker.ql-lineHeight .ql-picker-label[data-value="2"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="2"]::before {
    content: "2.0";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="2.1"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="2.1"]::before {
    content: "2.1";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="2.2"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="2.2"]::before {
    content: "2.2";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="2.3"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="2.3"]::before {
    content: "2.3";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="2.4"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="2.4"]::before {
    content: "2.4";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="2.5"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="2.5"]::before {
    content: "2.5";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="2.6"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="2.6"]::before {
    content: "2.6";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="2.7"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="2.7"]::before {
    content: "2.7";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="2.8"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="2.8"]::before {
    content: "2.8";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="2.9"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="2.9"]::before {
    content: "2.9";
  }
  .ql-picker.ql-lineHeight .ql-picker-label[data-value="3"]::before,
  .ql-picker.ql-lineHeight .ql-picker-item[data-value="3"]::before {
    content: "3.0";
  }
  .ql-editor {
    max-height: 500px;
  }
}

组件调用

<Quilleditor @content="onchangecontent" ref="Quilleditor">
</Quilleditor>
 // 富文本内容
 onchangecontent(event) {
     this.formValidate.content = event;
  }

lineHeight.js

import Quill from 'quill'
let Parchment = Quill.import('parchment');
class lineHeightAttributor extends Parchment.Attributor.Style {}
let lineHeight = new lineHeightAttributor('lineHeight', 'line-height', {
    scope: Parchment.Scope.INLINE,
    whitelist: ['1', '1.1','1.2','1.3','1.4','1.5','1.6','1.7','1.8','1.9','2','2.1','2.2','2.3','2.4','2.5','2.6','2.7','2.8','2.9','3']
});
Quill.register({ "formats/lineHeight": lineHeight }, true);

export default lineHeight;

调用图片放大缩小时要配置这个哦,不然会报错!

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值