大纲
前言
入职后的第一个项目就涉及富文本编辑器,接手时编辑器功能已开发的比较完善,我则是站在“前人的肩膀上前行”。此篇内容意在分享如何搭建一个富文本编辑器,及自己在开发过程中的踩坑经历。因项目使用 Quill
,故本文也以此为基础描述。
前戏:快速搭个富文本编辑器
虽项目为Quill
搭配Vue
,但Quill
实则为一个彻彻底底的“绿茶”,只要“爽”无论你是当红的Vue
、React
,还是“老当益壮”的jQuery
,它都愿意“跟”,哔~(人工消音)
本文则用
React
演示,为方便搭建则使用Parcel
进行构建
依赖
yarn add parcel-bundler quill react react-dom sass
npm jiǒ 本
{
// ...
"scripts": {
"clean": "rm -rf dist/ ./cache", // 不清理 ./cache 可能会造成页面刷新问题
"start": "yarn clean && parcel src/index.html"
},
// ...
}
欢迎 Quill 登场
index.js
:
import React from 'react';
import {
render} from 'react-dom';
import App from './app';
render(<App />, document.getElementById('app'));
index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Quill</title>
</head>
<body>
<div id="app"></div>
<script src="./index.js"></script>
</body>
</html>
app.js
:
import React, {
Component} from 'react';
import Quill from 'quill';
import './app.scss';
export default class QuillEditor extends Component {
constructor(props) {
super(props);
this.state = {
quill: null,
};
}
componentDidMount() {
const quill = new Quill('#editor', {
// param1: 编辑器挂载的节点
theme: 'snow', // 选择心仪的编辑器“皮肤”
});
this.setState({
quill});
}
render() {
return <div className="editor-wrapper">
<div id="editor"></div>
</div>;
}
};
app.scss
:
@import "../node_modules/quill/dist/quill.snow.css";
* {
margin: 0;
padding: 0;
}
.editor-wrapper {
width: 800px;
}
.ql-container.ql-snow {
height: 600px;
}
此时最基础的编辑器已搭建好,运行yarn start
会在浏览器看到如下界面:
通过上面的代码,大家可以看出这个“绿茶”的确与框架无关,它只要知道了它的”猎物“即可!
身子热乎了,来撸起袖子干
知己知彼
以上搭的编辑器仅有简单的有序/无序列表/加粗/斜体/下划线/超链接等功能,根本无法满足需求,所以接下来要解锁Quill
的更多”姿势“。扩充功能之前需了解Quill
中的几个基本概念:Parchment
/Blot
/Attributor
/Formats
/Modules
及Delta
。
Parchment: Quill
的文档模型,是一个和DOM
树平行的树结构,为Quill
提供一些可用的功能。
Blot: 一个Parchment
由多个Blot
组成,Blot
对应的是一个DOM节点,Blot
可以提供结格式化或内容等。让我们来康康Blot
源码中都有些什么,从而来帮助我们理解:
parchment/src/blot/inline.d.ts
:
// 暂且与DOM相对照介绍属性或方法含义
declare class TextBlot extends LeafBlot implements Leaf {
// ...
static blotName: string; // Blot的名字
// Blot是行内/块级还是其他scope(并不是指HTML中的块级元素等,是对于Blot而言)
static scope: Registry.Scope;
static value(domNode: Text): string; // DOM节点中的值
// ...
}
export default TextBlot;
Attributor: 可以提供格式化信息(下面将结合format
进行介绍);
Format: 在工具栏上的每一个功能都对应一个format
,工具栏的功能当然不止上图中的,用户也可以自定义工具栏(本文对自定义工具栏不做赘述,官方文档请点此处),让我们再来康康format
这葫芦里卖的什么药:
quill/formats/align.js
:
import Parchment from 'parchment';