安装依赖
npm install @vueup/vue-quill quill quill-image-uploader
自定义字体
把自定义字体样式放入font.css中在main.js中导入
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimSun]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimSun]::before {content: "宋体";font-family: "SimSun";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {content: "黑体";font-family: "SimHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {content: "微软雅黑";font-family: "Microsoft YaHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {content: "楷体";font-family: "KaiTi";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {content: "仿宋";font-family: "FangSong";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {content: "Arial";font-family: "Arial";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {content: "Times New Roman";font-family: "Times New Roman";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {content: "sans-serif";font-family: "sans-serif";
}.ql-font-SimSun {font-family: "SimSun";
}
.ql-font-SimHei {font-family: "SimHei";
}
.ql-font-Microsoft-YaHei {font-family: "Microsoft YaHei";
}
.ql-font-KaiTi {font-family: "KaiTi";
}
.ql-font-FangSong {font-family: "FangSong";
}
.ql-font-Arial {font-family: "Arial";
}
.ql-font-Times-New-Roman {font-family: "Times New Roman";
}
.ql-font-sans-serif {font-family: "sans-serif";
}
注册自定义字体到quill
案例
<template><div class="publish-form-container"><div class="publish-form"><form @submit.prevent="submitForm"><div class="form-group"><label for="content">内容</label><QuillEditor v-model="content" :options="editorOption" class="quill-editor" /></div><button type="submit" class="submit-btn">提交</button></form></div></div>
</template><script>
import { QuillEditor, Quill } from '@vueup/vue-quill';
import ImageUploader from 'quill-image-uploader';
import '@vueup/vue-quill/dist/vue-quill.snow.css';// 注册自定义字体到 Quill
const Font = Quill.import('formats/font');
Font.whitelist = ['SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong', 'Arial', 'Times-New-Roman', 'sans-serif'];
Quill.register(Font, true);// 注册图片上传模块
Quill.register("modules/imageUploader", ImageUploader);// 模拟上传API
const uploadFileAPI = async (fileData) => {// 模拟上传返回URLreturn new Promise((resolve) => {setTimeout(() => {resolve({ data: { filePath: 'https://lalallalal.com/' + fileData.file.name } });}, 1000);});
};// 将本地文件转换为URL
const getLocalImageURL = (file) => {return new Promise((resolve) => {const reader = new FileReader();reader.onload = (e) => {resolve(e.target.result);};reader.readAsDataURL(file);});
};export default {components: {QuillEditor,},data() {return {title: '',type: '',content: '',editorOption: {modules: {imageUploader: {upload: async (file) => {const localUrl = await getLocalImageURL(file);return localUrl; // 返回本地图片的 URL 进行预览},},toolbar: [[{ font: Font.whitelist }], // 字体['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: [] }], // 字体颜色,背景颜色[{ align: [] }], // 对齐['clean'], // 清除格式['link', 'image', 'video'], // 链接,图片,视频],},},};},methods: {// 提交表单方法async submitForm() {// 创建虚拟 DOM 来解析内容const parser = new DOMParser();const doc = parser.parseFromString(this.content, 'text/html');// 查找所有的本地图片const images = doc.querySelectorAll('img');const imageUploadPromises = [];images.forEach((img) => {const localSrc = img.getAttribute('src');// 如果是本地图片,上传图片并替换URLif (localSrc.startsWith('data:')) {const uploadPromise = uploadFileAPI({ file: this.dataURLtoFile(localSrc, 'image.png') }).then((res) => {img.setAttribute('src', res.data.filePath); // 替换成服务器上的图片URL});imageUploadPromises.push(uploadPromise);}});// 等待所有图片上传完成后提交表单try {await Promise.all(imageUploadPromises);// 上传完成后,更新内容const updatedContent = doc.body.innerHTML;const payload = {title: this.title,content: updatedContent,type: this.type,};console.log("提交的内容:", payload);const response = await fetch("/api/posts", {method: "POST",headers: {"Content-Type": "application/json",},body: JSON.stringify(payload),});const data = await response.json();console.log("发布成功", data);} catch (error) {console.error("发布失败", error);}},// 将 dataURL 转换为 File 对象的辅助函数dataURLtoFile(dataurl, filename) {const arr = dataurl.split(',');const mime = arr[0].match(/:(.*?);/)[1];const bstr = atob(arr[1]);let n = bstr.length;const u8arr = new Uint8Array(n);while (n--) {u8arr[n] = bstr.charCodeAt(n);}return new File([u8arr], filename, { type: mime });},},
};
</script><style lang="less" scoped>
//TODO
</style>
参考:在vue中Quill富文本编辑器的使用(主题、自定义工具栏、自定义字体选项、图片拖拽上传、图片改变大小)_quill-editor修改工具栏图标颜色-CSDN博客
Vue3使用vue-quill富文本编辑器并实现图片自定义上传替换默认base64格式图片_vue3 quill-CSDN博客