Vue3使用vue-quill富文本编辑器
安装依赖
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) => {
// 模拟上传返回URL
return 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');
// 如果是本地图片,上传图片并替换URL
if (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博客