vue富文本 vue-quill-editor + 上传图片到阿里云服务器 + 修改富文本内容

前言

使用富文本编辑器,需要将图片上传到服务器,完成之后,还需要在修改页面完成修改富文本内容,使用的富文本插件是vue-quill-editor,
在这里插入图片描述

一 、安装 vue-quill-editor

npm i vue-quill-editor
npm install quill --save
npm install quill-image-resize-module --save // 图片缩放组件引用
npm i quill-image-drop-module  -S // 图片拖动组件引用
npm install axios // 上传阿里云服务器用

二、引入

import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
import { quillEditor, Quill } from 'vue-quill-editor';
import axios from 'axios';

// 如果要图片拖拽功能,增加这两个插件
import { ImageDrop } from "quill-image-drop-module"; // 图片拖动组件引用
import ImageResize from "quill-image-resize-module"; // 图片缩放组件引用
Quill.register("modules/imageDrop", ImageDrop); // 注册
Quill.register("modules/imageResize", ImageResize); // 注册

三、配置 vue.config

const { defineConfig } = require('@vue/cli-service')
const webpack = require('webpack') // 引入webpack
module.exports = defineConfig({
  configureWebpack: {
    plugins: [
      new webpack.ProvidePlugin({
        'window.Quill': 'quill/dist/quill.js',
        'Quill': 'quill/dist/quill.js'
      })
    ]
  },
})

四 、上传图片到阿里云成功后的图片显示预览

在这里插入图片描述

五、富文本组件代码

<template>
  <div class="editor">
    <quill-editor class="ql-editor" v-model="content" ref="myQuillEditor" :options="editorOption"
      @blur="onEditorBlur($event)" @focus="onEditorFocus($event)" @change="onEditorChange($event)"></quill-editor>
  </div>
</template>

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

// 如果要图片拖拽功能,增加这两个插件
import { ImageDrop } from "quill-image-drop-module"; // 图片拖动组件引用
import ImageResize from "quill-image-resize-module"; // 图片缩放组件引用
Quill.register("modules/imageDrop", ImageDrop); // 注册
Quill.register("modules/imageResize", ImageResize); // 注册

export default {
  name: "customEditor",
  components: {
    quillEditor
  },
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  watch: {
    value(newValue) {
      this.content = newValue; // 监听 props.value 的变化
    },
    content(newValue) {
      this.$emit('content-changed', newValue); // 向父组件发出事件
    }
  },
  data() {
    return {
      content: this.value,
      editorOption: {
        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: [] }], //字体
            [{ align: [] }], //对齐方式
            ["clean"], //清除字体样式
            ["image",], //上传图片、上传视频 "video"
          ]
        },
        imageDrop: true,
        imageResize: {
          displayStyles: {
            backgroundColor: 'black',
            border: 'none',
            color: 'white'
          },
          modules: ['Resize', 'DisplaySize', 'Toolbar']
        }
      },
    };
  },
  mounted() {
  
    // 获取工具栏实例并覆盖图片处理函数
    const toolbar = this.$refs.myQuillEditor.quill.getModule('toolbar');
    toolbar.addHandler('image', this.handleImageUpload);
  },
  methods: {
    // 处理图片上传事件
    handleImageUpload() {
      const input = document.createElement('input');
      input.setAttribute('type', 'file');
      input.setAttribute('accept', 'image/*');
      input.onchange = async () => {
        const file = input.files[0];
        if (file) {
          await this.uploadImage(file);
        }
      };
      input.click();
    },
    // 上传图片到阿里云服务器
    async uploadImage(file) {
      // console.log("file", file);
      try {
        // 获取阿里云上传凭证
        const res = await this.$axios("feiyong/ossNews")
        // console.log("res", JSON.parse(JSON.stringify(res)));
        const formData = new FormData();
        const fileName = res.data.dir + res.data.gsid + '/' + `${Date.now()}_${Math.random()}`;

        // 添加必要字段
        formData.append("key", fileName); // 最终存储的文件名
        formData.append("policy", res.data.policy);
        formData.append("OSSAccessKeyId", res.data.accessid);
        formData.append('success_action_status', "200");
        formData.append("signature", res.data.signature);
        formData.append("callback", res.data.callback);
        formData.append("file", file); // 图片文件      

        // 发送上传请求
        const uploadRes = await axios.post(res.data.host, formData);
        // 获取图片URL
        const imageUrl = `${res.data.host}/${uploadRes.data.data.filename}${res.data.style2}`;
        // const imageUrl = `${res.data.host}/${uploadRes.data.data.filename}${res.data.style1}`;
        // 插入图片到编辑器
        this.insertImageToEditor(imageUrl);
      } catch (error) {
        console.error('上传失败', error.response ? error.response.data : error.message);
      }
    },
    // 插入图片到编辑器
    insertImageToEditor(url) {
      const range = this.$refs.myQuillEditor.quill.getSelection();
      this.$refs.myQuillEditor.quill.insertEmbed(range.index, 'image', url);
      this.$refs.myQuillEditor.quill.setSelection(range.index + 1);
    },
    async onEditorChange({ html}) {
      // console.log(quill, "quill");
      // console.log(text, "text");
      // console.log(html, "html");
      this.content = html;
      this.$emit('content-changed', html); // 发出事件
    },
    onEditorBlur(e) {
      console.log(e, '失去焦点事件');
    },
    onEditorFocus(e) {
      console.log(e, '获得焦点事件');
    },
  },

};
</script>

<style lang="less">
.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: "等宽字体";
}

.edit_container {
  width: 100%;
}

:deep(.ql-editor) {
  min-height: 400px;
}
</style>


六、 父页面使用富文本组件

修改的时候直接赋值就可以获取到原来的内容

<template>
    <fuwenben @content-changed="handleContentChange" v-model="editorContent"></fuwenben>
</template>
<script>
import fuwenben from '@/components/fuwenben/fuwenben'
export default {
 name: "WenZhang",
  data() {
    return {
        editorContent: '',
        }
 },
 methods: {
     handleContentChange(content) {
      this.editorContent = content;
    },
  }
 }
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值