实现富文本框根据光标位置上传图片

259 阅读1分钟

使用的库:vue-quill ,很可惜没有中文文档

1.下包

2.引入

import { QuillEditor } from "@vueup/vue-quill";
import "@vueup/vue-quill/dist/vue-quill.snow.css";

3.创建一个富文本编辑器

4.使用的主要api

  • getModule: 获取编辑器的工具栏
  • addHandler: 给工具栏添加工具和工具的方法
  • getSelection: 获取光标位置
  • getSelection: 设置光标位置
  • insertEmbed: 添加图片
<template>
    <div>
        <QuillEditor
            ref="myQuillEditor"
            theme="snow"
            v-model:content="content"
            :options="data.editorOption"
            contentType="html"
            @update:content="setValue()"
        />
        <!-- 使用自定义图片上传 -->
        <input type="file" hidden accept=".jpg,.png" ref="fileBtn" @change="handleUpload" />
    </div>
</template>

<script setup>
import { QuillEditor } from "@vueup/vue-quill";
import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { reactive, onMounted, ref, toRaw, watch } from "vue";
// 图片上传api
import { upload } from "@/api/common.js";

const props = defineProps(["value"]);
const emit = defineEmits(["updateValue"]);
const content = ref("");
const myQuillEditor = ref(null);

watch(
    () => props.value,
    (val) => {
        toRaw(myQuillEditor.value).setHTML(val);
    },
    { deep: true }
);
const fileBtn = ref();
const data = reactive({
    content: "",
    editorOption: {
        modules: {
            toolbar: [
                ["bold", "italic", "underline", "strike"],
                [{ size: ["small", false, "large", "huge"] }],
                [{ align: [] }],
                [{ list: "ordered" }, { list: "bullet" }],
                [{ indent: "-1" }, { indent: "+1" }],
                [{ header: 1 }, { header: 2 }],
                ["image"],
                ["clean"],
                [{ direction: "rtl" }],
                [{ color: [] }, { background: [] }]
            ]
        },
        placeholder: "请输入内容..."
    }
});
const imgHandler = (state) => {
    if (state) {
        fileBtn.value.click();
    }
};
const setValue = () => {
    const text = myQuillEditor.value.getHTML();
    emit("updateValue", text);
};
const handleUpload = (e) => {
    const files = Array.prototype.slice.call(e.target.files);
    console.log(files, "files");
    if (!files) {
        return;
    }
    const formdata = new FormData();
    formdata.append("file", files[0]);
    // 这里的upload写你自己的上传ajax请求
    upload(formdata).then((res) => {
        if (res.url) {
            const quill = toRaw(myQuillEditor.value).getQuill();
            const length = quill.getSelection().index;
            // 插入图片,res为服务器返回的图片链接地址
            quill.insertEmbed(length, "image", res.url);
            // 调整光标到最后
            quill.setSelection(length + 1);
        }
    });
};
onMounted(() => {
    const quill = myQuillEditor.value.getQuill();
    if (myQuillEditor.value) {
        quill.getModule("toolbar").addHandler("image", imgHandler);
    }
});