react-quill 是一个基于 React 的富文本编辑器组件,它基于 Quill 富文本编辑器库。本文主要介绍了基础配置及使用,图片 base64 转地址处理,自定义字体、字号、行间距等的实现。
该富文本编辑器是 antd 社区精选组件中推荐的,具体可以查看官网:ant-design.antgroup.com/docs/react/…
Github 地址为:github.com/zenoamaro/r…
1. 安装及基础使用
- 安装依赖ReactQuill
# 安装
npm install react-quill --save
- 引入及使用:
react-quill 提供了许多配置选项,可以自定义编辑器的行为和外观。
以下是一些常用的配置选项:
theme: 设置编辑器的主题,可选值有 'snow' 和 'bubble'。modules: 配置编辑器的功能模块,如工具栏、历史记录等。formats: 指定编辑器支持的格式。
// 引入组件及样式
import ReactQuill, { Quill } from "react-quill";
import "react-quill/dist/quill.snow.css";
// 使用组件
<ReactQuill
theme="snow"
onChange={handleEditorChange}
value={content}
modules={quillToolbar}
/>;
// 数据绑定到form表单
const [content, setContent] = useState("");
const handleEditorChange = (content: any) => {
setContent(content);
form.setFieldsValue({ content: content });
};
2. 基础配置
具体可查看官方文档:quilljs.com/docs/module…
以下是一些常用的基础配置
export const quillToolbar = {
toolbar: [
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
[{ font: [] }], // 字体
[{ size: [] }], // 字号
[
{ color: [] }, // 文字颜色
{ background: [] }, // 背景色
],
[
"bold", // 加粗
"italic", // 斜体
"underline", // 下划线
"strike", // 删除线
"blockquote", // 引用
"code-block", // 代码块
],
[{ script: "sub" }, { script: "super" }], // superscript(x2)/subscript
[{ align: [] }], // 对齐方式
[{ indent: "-1" }, { indent: "+1" }],
[{ direction: "rtl" }],
[
"link", // 链接
"image", // 图片
"video", // 视频
// "formula", // 数学函数
],
[
{ list: "ordered" }, // 有序列表
{ list: "bullet" }, // 无序列表
{ list: "check" }, // 选中列表
],
["clean"], // 清除按钮
],
};
基础配置展示如下所示:
3. 图片 base64 转为地址上传
react-quill 提供了多种事件处理方法,如 onChange、onFocus、onBlur 等,可以根据需要进行处理。
默认情况下,react-quill 富文本编辑器中上传图片时,是将图片转为 base64 数据保存的,这样的话,保存到数据库中时,数据太大了,很不方便。所以最好的方式,是先传到服务器上,富文本组件中,只上传图片地址就行。
处理逻辑如下所示:在onChange事件中,判断是否是图片,如果是图片,就上传到服务器,并返回地址,否则就返回原来的数据。
3.1 base64toFile
base64toFile:图片 base64 数据转为文件
export function base64toFile(base64String: string): File {
// 去掉 base64 字符串的前缀(如 "data:image/png;base64,")
const base64Data = base64String.replace(/^data:image\/\w+;base64,/, "");
// 将 base64 字符串解码为二进制数据
const byteCharacters = atob(base64Data);
// 将二进制数据转换为字节数组
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
// 创建一个 Uint8Array
const uint8Array = new Uint8Array(byteNumbers);
// 创建 Blob 对象
const blob = new Blob([uint8Array], { type: "image/png" });
// 生成唯一的文件名
const filename = `image_${Date.now()}.png`;
// 创建 File 对象
const file = new File([blob], filename, { type: "image/png" });
return file;
}
3.2 handleEditorChange
handleEditorChange:图片文件上传到服务器,替换富文本编辑器中的内容。具体实现如下所示:
const handleEditorChange = (ctx: any, delta: any, source: any, editor: any) => {
// 图片上传后为base64,上传至服务器文件过大,所以需要将base64格式图片进行转换,具体方法如下:
let delta_ops = delta.ops;
// 获取富文本内容
let quillContent = editor.getContents();
if (delta_ops && delta_ops.length) {
quillContent?.ops?.map(async (item: any) => {
if (item.insert) {
let imgStr = item.insert.image;
// 判断是否为图片
if (imgStr && imgStr?.startsWith("data:image/")) {
let file = base64toFile(imgStr);
// 调用文件上传接口:将二进制图片文件上传至服务器,服务器返回一个图片地址
const result: any = await OssClient.uploadFile(OssPath.AQuill, file);
// 更新为图片地址
item.insert.image = result.filePath;
// 设置新的富文本内容
setContent(quillContent);
// 设置表单数据
form.setFieldsValue({ content: quillContent });
} else {
setContent(ctx);
form.setFieldsValue({ content: ctx });
}
}
});
}
};
4. 自定义字号
正常情况下,字号只有 small、normal、large、huge 等 4 中,不符合我们的使用习惯,一般都是使用 px 来定义的,因此需要自定义处理一下。
- 自定义字号
export const sizeArr = ["ft12", "ft14", "ft16", "ft18", "ft20", "ft24", "ft32"];
export const quillToolbar = {
toolbar: [
[{ size: sizeArr }], // 字号大小
],
};
- 自定义 quill 编辑器的字号
import ReactQuill, { Quill } from "react-quill";
import "react-quill/dist/quill.snow.css";
const FontAttributor = Quill.import("attributors/class/size");
FontAttributor.whitelist = sizeArr;
Quill.register(FontAttributor, true);
- 自定义字号样式实现
如下所示:举例写了 3 个,12px、14px、32px,其他的自己补充就行,注意:必须一一对应
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="ft12"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="ft12"]::before {
content: "12px";
font-size: 12px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="ft32"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="ft32"]::before {
content: "32px";
font-size: 32px;
}
.ql-size-ft12 {
font-size: 12px;
}
.ql-size-ft14 {
font-size: 14px;
}
.ql-size-ft32 {
font-size: 32px;
}
5. 自定义字体
正常情况下,字体也是不常见的,也需要自定义处理一下,也需要引入对应的字体文件。
- 自定义字体
export const fontArr = [
"SimSun", // 宋体
"SimHei", // 黑体
"Microsoft-YaHei", // 微软雅黑
"KaiTi", // 楷体
"FangSong", // 仿宋
];
export const quillToolbar = {
toolbar: [
[{ font: fontArr }], // 字体
],
};
- 自定义 quill 编辑器的字体
const Font = Quill.import("formats/font");
Font.whitelist = fontArr; // 将字体加入到白名单
Quill.register(Font, true); // 注册字体
- 自定义字体样式实现
.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 {
font-family: "SimSun" !important;
content: "宋体";
}
/* 设置每个字体的css字体样式,举例一个 */
.ql-font-SimSun {
font-family: "SimSun";
}
完整配置如下所示:
6. 自定义行高
默认没有行高这个属性配置,需要完全自定义处理,配置和上面的差不多
// 1. 配置行高属性
export const lineHeightArr = ["1", "1.5", "1.75", "2", "3"];
// 2. 定义行高选项配置
export const quillToolbar = {
toolbar: [
[{ "line-height": lineHeightArr }], // 行间距
],
};
// 3. 注册行高配置
const Parchment = Quill.import("parchment");
const lineHeightStyle = new Parchment.Attributor.Style(
"lineHeight",
"line-height",
{
scope: Parchment.Scope.INLINE,
whitelist: lineHeightArr,
}
);
Quill.register({ "formats/lineHeight": lineHeightStyle }, true);
/* 4. 行高样式 */
.ql-snow .ql-picker.ql-line-height .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-line-height .ql-picker-item[data-value="2"]::before {
content: "2";
}