做前端项目时,一般都会遇到富文本编辑的功能,主要处理的就是这个框架处理图片是以base64的方式,而我们实际中一般会先将图片传到服务器,然后用服务器返回的地址放到富文本中.还有就是会遇到粘贴,拖拽图片的处理
效果图
- 主要代码
<template>
<div>
<quill-editor
class="editor"
@change="onEditorChange($event)"
ref="quill"
v-model="content"
:options="editorOption"
></quill-editor>
<input type="file" @change="uploadImg" id="upload" style="display: none" />
<div v-html="content" style="margain-top: 50px"></div>
</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 { container, ImageExtend, QuillWatch } from "quill-image-extend-module";
import ImageResize from "quill-image-resize-module"; // 引用
import { ImageDrop } from "quill-image-drop-module";
Quill.register("modules/imageDrop", ImageDrop);
Quill.register("modules/imageResize", ImageResize); // 注册
Quill.register("modules/ImageExtend", ImageExtend);
export default {
name: "",
components: {
quillEditor,
},
data() {
return {
content: "", // 富文本编辑器默认内容
editorOption: {
// 富文本编辑器配置
modules: {
imageResize: {
displayStyles: {
backgroundColor: "black",
border: "none",
color: "white",
},
modules: ["Resize", "DisplaySize", "Toolbar"],
},
ImageExtend: {
loading: true,
name: "file",
action: "/api/oa/Handler/Upload/UploadFile",
response: (res) => {
return res.file_url;
},
},
toolbar: {
container: container,
handlers: {
image: function () {
QuillWatch.emit(this.quill.id);
},
},
},
},
theme: "snow",
placeholder: "请输入正文",
},
};
},
mounted() {
this.init();
},
methods: {
// 富文本编辑器 内容改变事件
onEditorChange({ quill, html, text }) {
console.log("editor change!", quill, html, text);
},
// 上传图片
uploadImg(data) {
//构造formData对象
try {
this.$request.post({
url: "/oa/Handler/Upload/UploadFile",
isForm: true,
data: data,
success: (res) => {
//返回上传文件的地址
let url = res.file_url;
if (url != null && url.length > 0) {
let length = this.$refs.quill.quill.getSelection().index; //光标位置
// 插入图片地址
this.$refs.quill.quill.insertEmbed(length, "image", url);
// 光标后移一位
this.$refs.quill.quill.setSelection(length + 1);
}
},
});
} catch ({ message: msg }) {
console.log(msg);
}
},
init() {
let quill = this.$refs.quill.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;
}
let data = { file: file };
this.uploadImg(data);
});
}
},
false
);
},
},
};
</script>
<style lang='scss' >
.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>
如果遇到imports的错误,在vue.config.js中配置下就行了
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
'window.Quill': 'quill/dist/quill.js',//注意路径,可能与你们路径不一致
'Quill': 'quill/dist/quill.js' //注意路径,可能与你们路径不一致
}),
]
},