vue-quill-editor 修改上传图片或粘贴图片为 上传到服务器 方式。

如何下载引入就不说了,自行百度。

这个默认上传图片是将图片转为了base64了,所以在上传图片后,将数据传给后端时,数据过大,导致各种报错问题, 还有它也可以直接粘贴图片进去也是base64, 这里将上传图片更改为上传到自己服务器上,返回的是一个地址,这就方便多了。

直接开始:

先说组件结构:

 index.vue 就是组件 ,修改 粘贴图片上传在这个里面

quillConfig.js 是富文本的配置项  修改点击图片上传在这个里面

代码 :

index.vue

<template>
  <quill-editor ref="myTextEditor" class="editorBox" :options='editorOption' v-model="data" :style="{'height':height+'px', marginBottom: marginB+'px'}" :disabled='disabled'></quill-editor>
</template>

<script>
import { Quill } from "vue-quill-editor";
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
import quillConfig from './quillConfig';
import { getToken } from "@/utils/auth";
export default {
  components: {

  },
  props: {
    value: String,//绑定的值,在组件上使用 v-model 绑定一个值
    // 高度设置
    height: {
      type: [Number, String],
      default: 240
    },
    // 下边距距离
    marginB: {
      type: [Number, String],
      default: 10
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  model: {
    prop: 'value',
    event: 'change'
  },
  data() {
    return {
      data: '',//富文本绑定的值
      editorOption: quillConfig
    };
  },
  computed: {

  },
  created() {

  },
  watch: {
    value: {
      handler(newVal) {
        if (newVal) {
          this.data = newVal;
        }
      },
      deep: true,
      immediate: true
    },
    data(newVal) {
      this.$emit('change', newVal)
    },
    disabled: {
      handler(newVal) {
        if (newVal) {
          this.$nextTick(() => {
            var father = document.getElementsByClassName('editorBox')[0];
            var children = document.getElementsByClassName('ql-toolbar')[0];
            father.removeChild(children)
          })
        }
      },
      deep: true,
      immediate: true,
    },
  },
  methods: {
    //  自定义粘贴图片功能
    init() {
      let quill = this.$refs.myTextEditor.quill;
      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)
          })
        }
      }, false)
    },
    // 修改粘贴图片为上传到服务器
    uploadToServer(file) {
      const uploadConfig = {
        action: process.env.VUE_APP_BASE_API + "/common/upload", // 必填参数 图片上传地址
        methods: 'POST', // 必填参数 图片上传方式
        token: "Bearer " + getToken(), // 可选参数 如果需要token验证,假设你的token有存放在sessionStorage
        name: 'file', // 必填参数 文件的参数名
      };
      var xhr = new XMLHttpRequest()
      var formData = new FormData()
      formData.append(uploadConfig.name, file)
      xhr.open(uploadConfig.methods, uploadConfig.action, true);
      xhr.setRequestHeader("Authorization", uploadConfig.token);  //设置请求头
      xhr.send(formData)
      let quill = this.$refs.myTextEditor.quill;
      // 上传数据成功,会触发
      xhr.onload = function (res) {
        if (xhr.status === 200) {
          var res = JSON.parse(xhr.responseText);
          let length = quill.getSelection(true).index;
          //这里很重要,你图片上传成功后,img的src需要在这里添加,res.path就是你服务器返回的图片链接。            
          quill.insertEmbed(length, 'image', res.data);
          quill.setSelection(length + 1)
        }
      };
      // 上传数据完成(成功或者失败)时会触发
      xhr.upload.onerror = function (e) {
        this.$message.error('图片上传失败');
      };
    },
  },
  mounted() {
    this.init();

    //修改富文本设置字体大小
    let fontSizeStyle = Quill.import('attributors/style/size') //引入这个后会把样式写在style上
    fontSizeStyle.whitelist = ['13px', '16px', '18px', '20px', '30px', '40px', '50px', '60px']
    Quill.register(fontSizeStyle, true)

    //设置字体样式
    let Font = Quill.import('attributors/style/font') //引入这个后会把样式写在style上
    let fonts = [false, 'Microsoft-YaHei', 'SimSun', 'SimHei', 'KaiTi', 'FangSong']
    Font.whitelist = fonts //将字体加入到白名单
    Quill.register(Font, true)
  },
};
</script>

<style scoped lang="scss">
.editorBox {
  width: 100%;
  display: flex;
  flex-direction: column;
  /deep/.ql-container {
    flex: 1 !important;
    overflow: hidden;
  }
}
/*
这里一定要写上,是用来把相关改变的配置在工具栏正常显示
如果不写,字体样式的下拉会重复显示Sans Serif,字体大小的下拉会重复显示Normal
*/

// .quill-editor /deep/ .ql-container {
//   min-height: 150px;
// }
.quill-editor /deep/ .ql-picker-label {
  line-height: 24px;
  vertical-align: 4px;
}
.quill-editor /deep/ .ql-picker-options {
  max-height: 200px;
  overflow: auto;

  &::-webkit-scrollbar {
    width: 3px;
    height: 5px;
  }

  &::-webkit-scrollbar-track {
    background: transparent;
    border-radius: 10px;
  }
  &::-webkit-scrollbar-thumb {
    background: transparent;
    border-radius: 10px;
  }

  &:hover {
    &::-webkit-scrollbar-thumb {
      background: rgb(68, 164, 202);
      border-radius: 10px;
    }
  }
}
.quill-editor
  /deep/
  .ql-picker.ql-font
  .ql-picker-label[data-value="SimSun"]::before,
.quill-editor
  /deep/
  .ql-picker.ql-font
  .ql-picker-item[data-value="SimSun"]::before {
  content: "宋体";
  font-family: "SimSun" !important;
}
.quill-editor
  /deep/
  .ql-picker.ql-font
  .ql-picker-label[data-value="SimHei"]::before,
.quill-editor
  /deep/
  .ql-picker.ql-font
  .ql-picker-item[data-value="SimHei"]::before {
  content: "黑体";
  font-family: "SimHei";
}
.quill-editor
  /deep/
  .ql-picker.ql-font
  .ql-picker-label[data-value="Microsoft-YaHei"]::before,
.quill-editor
  /deep/
  .ql-picker.ql-font
  .ql-picker-item[data-value="Microsoft-YaHei"]::before {
  content: "微软雅黑";
  font-family: "Microsoft YaHei";
}
.quill-editor
  /deep/
  .ql-picker.ql-font
  .ql-picker-label[data-value="KaiTi"]::before,
.quill-editor
  /deep/
  .ql-picker.ql-font
  .ql-picker-item[data-value="KaiTi"]::before {
  content: "楷体";
  font-family: "KaiTi" !important;
}
.quill-editor
  /deep/
  .ql-picker.ql-font
  .ql-picker-label[data-value="FangSong"]::before,
.quill-editor
  /deep/
  .ql-picker.ql-font
  .ql-picker-item[data-value="FangSong"]::before {
  content: "仿宋";
  font-family: "FangSong";
}
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-label[data-value="60px"]::before,
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-item[data-value="60px"]::before {
  content: "一号";
}
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-label[data-value="50px"]::before,
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-item[data-value="50px"]::before {
  content: "二号";
}
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-label[data-value="40px"]::before,
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-item[data-value="40px"]::before {
  content: "三号";
}

.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-label[data-value="30px"]::before,
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-item[data-value="30px"]::before {
  content: "四号";
}
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-label[data-value="20px"]::before,
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-item[data-value="20px"]::before {
  content: "五号";
}
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-label[data-value="18px"]::before,
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-item[data-value="18px"]::before {
  content: "六号";
}
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-label[data-value="16px"]::before,
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-item[data-value="16px"]::before {
  content: "七号";
}
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-label[data-value="13px"]::before,
.quill-editor
  /deep/
  .ql-snow
  .ql-picker.ql-size
  .ql-picker-item[data-value="13px"]::before {
  content: "默认";
}
</style>

quillConfig.js 文件

import { getToken } from "@/utils/auth";
import { Message } from 'element-ui';
/*富文本编辑图片上传配置*/
const uploadConfig = {
  action: process.env.VUE_APP_BASE_API + "/common/upload", // 必填参数 图片上传地址
  methods: 'POST', // 必填参数 图片上传方式
  token: "Bearer " + getToken(), // 可选参数 如果需要token验证,假设你的token有存放在sessionStorage
  name: 'file', // 必填参数 文件的参数名
  size: 2000, // 可选参数   图片大小,单位为Kb, 1M = 1024Kb
  accept: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon' // 可选 可上传的图片格式
};
// toolbar工具栏的工具选项
const toolOptions = [
    ['bold', 'italic', 'underline', 'strike'],        // 加粗,斜体,下划线,删除线
    [{ 'header': 1 }, { 'header': 2 }],               // 几级标题
    [{ 'list': 'ordered' }, { 'list': 'bullet' }],     // 有序列表,无序列表
    [{ 'script': 'sub' }, { 'script': 'super' }],      // 下角标,上角标
    [{ 'indent': '-1' }, { 'indent': '+1' }],          // 缩进
    [{ 'size': ['13px', '16px', '18px', '20px', '30px', '40px', '50px', '60px'] }],  // 字体大小
    [{ 'color': [] }, { 'background': [] }],          // 颜色选择
    [{ 'font': ['Microsoft-YaHei', 'SimSun', 'SimHei', 'KaiTi', 'FangSong'] }],// 字体
    [{ 'align': [] }], // 居中
    ['clean'], // 清除样式
    ['link', 'image']
  ];
// 处理图片上传事件,更改为base64为上传到服务器
const handlers = {
  image: function image() {
    var self = this;

    var fileInput = this.container.querySelector('input.ql-image[type=file]');
    if (fileInput === null) {
      fileInput = document.createElement('input');
      fileInput.setAttribute('type', 'file');
      // 设置图片参数名
      if (uploadConfig.name) {
        fileInput.setAttribute('name', uploadConfig.name);
      }
      // 可设置上传图片的格式
      fileInput.setAttribute('accept', uploadConfig.accept);
      fileInput.classList.add('ql-image');
      // 监听选择文件
      fileInput.addEventListener('change', function () {
        // 创建formData
        var formData = new FormData();
        formData.append(uploadConfig.name, fileInput.files[0]);
        // 图片上传
        var xhr = new XMLHttpRequest();
        xhr.open(uploadConfig.methods, uploadConfig.action, true);
        xhr.setRequestHeader("Authorization",uploadConfig.token);  //设置请求头
        // 上传数据成功,会触发
        xhr.onload = function (res) {
          if (xhr.status === 200) {
            var res = JSON.parse(xhr.responseText);
            let length = self.quill.getSelection(true).index;
            //这里很重要,你图片上传成功后,img的src需要在这里添加,res.path就是你服务器返回的图片链接。            
            self.quill.insertEmbed(length, 'image', res.data);
            self.quill.setSelection(length + 1)
          }
          fileInput.value = '';

        };
        // 开始上传数据
        xhr.upload.onloadstart = function (e) {
          fileInput.value = ''
        };
        // 当发生网络异常的时候会触发,如果上传数据的过程还未结束
        xhr.upload.onerror = function (e) {
          Message.error({
            message:'图片上传失败'
          })
        };
        // 上传数据完成(成功或者失败)时会触发
        xhr.upload.onloadend = function (e) {
          // console.log('上传结束')
        };
        xhr.send(formData)
      });
      this.container.appendChild(fileInput);
    }
    fileInput.click();
  }
};

export default {
  placeholder: '请输入内容',
  modules: {
    toolbar: {
      container: toolOptions, // 工具栏选项
      handlers: handlers // 事件重写
    }
  }
};

这就完成了

使用 :

 <text-editor v-model='formData.remark' :disabled='disabled' height='300'></text-editor>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值