DevUI – это команда, которая занимается как проектированием, так и проектированием, обслуживая HUAWEI CLOUD.DevCloudПлатформа и несколько промежуточных и серверных систем в Huawei предназначены для дизайнеров и проектировщиков.
Официальный сайт:devui.design
Библиотека компонентов Ng:ng-devui(Добро пожаловать в Звезду)
введение
Эта статья основана наDevUI的富文本编辑器开发实践а такжеQuill源码написано.
EditorX этоDevUIПростой в использовании, простой в использовании и мощный редактор форматированного текста, разработанныйQuill, и он был значительно расширен для расширения возможностей редактора.
Квилл — этоAPI驱动,служба поддержки格式和模块定制Текстовый веб-редактор с открытым исходным кодом, в настоящее время имеет более 10 звезд на Github.25k.
Если вы не были в контакте с Quill, рекомендуется зайти на официальный сайт Quill, чтобы понять его основные концепции.
Прочитав эту статью, вы получите:
- Узнайте, что такое модуль Quill и как настроить модуль Quill.
- Зачем создавать модуль Quill и как создать собственный модуль Quill
- Как модули Quill взаимодействуют с Quill
- Углубленный взгляд на модульную механику Quill.
Предварительное исследование модуля Quill
Любой, кто использовал Quill для разработки приложений с форматированным текстом, должен знать о модулях Quill.
Например, когда нам нужно настроить наши собственные кнопки панели инструментов, мы настраиваем модуль панели инструментов:
var quill = new Quill('#editor', {
theme: 'snow',
modules: {
toolbar: [['bold', 'italic'], ['link', 'image']]
}
});
один из нихmodulesПараметры используются для настройки модуля.
toolbarПараметр используется для настройки модуля панели инструментов.Здесь передается двумерный массив, представляющий сгруппированные кнопки панели инструментов.
Визуализированный редактор будет содержать 4 кнопки панели инструментов:
Чтобы увидеть приведенную выше демонстрацию, пожалуйста, сердито ткнитеПанель инструментов модуля конфигурации.
Модуль Quill — это обычный класс JS.
Так что же такое модуль Quill? Почему мы должны понимать и использовать модуль Quill?
Модуль Quill на самом деле一个普通的JavaScript类, есть конструкторы, есть переменные-члены и есть методы.
Ниже приведена приблизительная структура исходного кода модуля панели инструментов:
class Toolbar {
constructor(quill, options) {
// 解析传入模块的工具栏配置(就是前面介绍的二维数组),并渲染工具栏
}
addHandler(format, handler) {
this.handlers[format] = handler;
}
...
}
Вы можете видеть, что модуль панели инструментов — это обычный JS-класс. Экземпляр quill и конфигурация параметров передаются в конструкторе, а класс модуля может управлять редактором и управлять им, получая экземпляр quill.
Например, модуль панели инструментов создаст контейнер панели инструментов в соответствии с конфигурацией параметров, заполнит контейнер кнопкой/раскрывающимся списком и другими элементами и привяжет события обработки кнопки/раскрывающегося списка. Конечным результатом является панель инструментов, отображаемая над телом редактора, которую можно использовать для форматирования элементов в редакторе или вставки новых элементов в редактор с помощью кнопок панели инструментов/раскрывающихся списков.
Модуль Quill очень мощный, мы можем использовать его для扩展编辑器的能力, чтобы достичь желаемой функции.
В дополнение к модулю панели инструментов в Quill также встроено несколько очень полезных модулей, давайте посмотрим.
Встроенные модули Quill
Quill имеет в общей сложности 6 встроенных модулей:
- Версия вставки из буфера обмена
- История История операций
- События клавиатуры клавиатуры
- Подсветка синтаксиса синтаксиса
- Панель инструментов
- Загрузка файла загрузчиком
Буфер обмена, История и Клавиатура — это встроенные модули, необходимые Quill, которые включаются автоматически и могут быть настроены, но не отменены. в:
Модуль буфера обмена обрабатывает события копирования/вставки, сопоставление узлов HTML-элементов и преобразование HTML в Delta.
Модуль «История» поддерживает стек операций и записывает каждую операцию редактора, например вставку/удаление контента, форматирование контента и т. д., что может легко реализовать такие функции, как отмена/повтор.
Модуль Keyboard используется для настройки событий клавиатуры и обеспечивает удобство реализации сочетаний клавиш.
Модуль Syntax используется для подсветки синтаксиса кода.Это зависит от внешней библиотеки highlight.js, которая по умолчанию отключена.Чтобы использовать функцию подсветки синтаксиса, highlight.js должен быть установлен и включен вручную.
Другие модули представлены не так много, если вы хотите узнать больше, вы можете обратиться кДокументация модуля Quill.
Конфигурация модулей Quill
Мы только что упомянули модуль событий Keyboard.Давайте возьмем еще один пример, чтобы углубить наше понимание конфигурации модуля Quill.
Модуль «Клавиатура» по умолчанию поддерживает множество сочетаний клавиш, например:
- Жирный ярлык — Ctrl+B;
- Горячая клавиша для гиперссылок — Ctrl+K;
- Горячая клавиша для отмены/назад — Ctrl+Z/Y.
Но он не поддерживает сочетание клавиш зачеркивания, если мы хотим настроить сочетание клавиш зачеркивания, скажемCtrl+Shift+S, мы можем настроить его следующим образом:
modules: {
keyboard: {
bindings: {
strike: {
key: 'S',
ctrlKey: true,
shiftKey: true,
handler: function(range, context) {
const format = this.quill.getFormat(range);
this.quill.format('strike', !format.strike);
}
},
}
},
toolbar: [['bold', 'italic', 'strike'], ['link', 'image']]
}
Чтобы увидеть приведенную выше демонстрацию, пожалуйста, сердито ткнитеНастройте модуль клавиатуры.
В процессе разработки редактора форматированного текста с помощью Quill мы столкнемся с различными модулями и создадим множество пользовательских модулей, каждый из которых настраивается с помощью параметра modules.
Далее мы попытаемся создать собственный модуль, чтобы углубить наше понимание модулей Quill и их конфигурации.
Создание пользовательских модулей
Из введения в предыдущем разделе мы узнали, что модуль Quill на самом деле является обычным классом JS, и в нем нет ничего особенного.В параметрах инициализации класса экземпляр Quill и параметры конфигурации модуля будут переданы в , а затем вы можете управлять И расширять функциональные возможности редактора.
Когда встроенные модули Quill не могут удовлетворить наши потребности, нам нужно создавать собственные модули для достижения желаемой функциональности.
Например, в компоненте расширенного текста EditorX есть функция для подсчета текущего количества слов в редакторе.Эта функция реализована с помощью специального модуля.Ниже мы шаг за шагом представим, как инкапсулировать эту функцию в независимую функцию.Counterмодуль.
Существует три шага для создания модуля Quill:
Шаг 1: Создайте класс модуля
Создайте новый файл JS с обычным классом JavaScript.
class Counter {
constructor(quill, options) {
console.log('quill:', quill);
console.log('options:', options);
}
}
export default Counter;
Это пустой класс, ничего, просто вывод опций экземпляра Quill и информации о конфигурации модуля в процессе инициализации.
Шаг 2: Настройте параметры модуля
modules: {
toolbar: [
['bold', 'italic'],
['link', 'image']
],
counter: true
}
Сначала мы не передавали данные конфигурации, а просто включили модуль и обнаружили, что никакая информация не печатается.
Шаг 3: Зарегистрируйте модуль
Для использования модуля необходимо вызвать метод Quill.register для регистрации класса модуля перед инициализацией Quill (подробно принцип мы опишем позже), а так как нам нужно расширить модуль, префикс должен начинаться с модулей :
import Quill from 'quill';
import Counter from './counter';
Quill.register('modules/counter', Counter);
На данный момент мы видим, что информация была напечатана.
Логика добавления модулей
В это время мы добавляем некоторую логику в счетчик счетчика, чтобы подсчитать количество слов в текущем контент редактора:
constructor(quill, options) {
this.container = quill.addContainer('ql-counter');
quill.on(Quill.events.TEXT_CHANGE, () => {
const text = quill.getText(); // 获取编辑器中的纯文本内容
const char = text.replace(/\s/g, ''); // 使用正则表达式将空白字符去掉
this.container.innerHTML = `当前字数:${char.length}`;
});
}
В методе инициализации модуля Counter мы вызываем предоставленный QuilladdContainerметод, добавьте пустой контейнер для редактора для хранения содержимого модуля подсчета слов, а затем привяжите событие изменения содержимого редактора, чтобы при вводе содержимого в редакторе количество слов можно было подсчитывать в режиме реального времени.
В событии Text Change мы вызываем метод getText экземпляра Quill, чтобы получить текстовое содержимое в редакторе, затем используем регулярные выражения для удаления пробельных символов и, наконец, вставляем информацию о количестве слов в контейнер количества символов.
Общий эффект от показа следующий:
Чтобы увидеть приведенную выше демонстрацию, пожалуйста, сердито ткнитеПользовательский модуль статистики персонажей.
механизм загрузки модуля
Получив предварительное представление о модуле Quill, мы захотим узнать, как работает модуль Quill.Далее мы начнем с процесса инициализации Quill и подробно обсудим механизм загрузки модуля Quill на примере модуля панели инструментов. (Это резюме включает в себя анализ исходного кода Quill. Если вы ничего не понимаете, оставьте сообщение для обсуждения.)
Инициализация класса Quill
Когда мы выполним new Quill(), будет выполнен метод-конструктор класса Quill, который находится в исходном коде Quill.core/quill.jsв файле.
Примерная структура исходного кода метода инициализации выглядит следующим образом (удалить код, не относящийся к загрузке модуля):
constructor(container, options = {}) {
this.options = expandConfig(container, options); // 扩展配置数据,包括增加主题类等
...
this.theme = new this.options.theme(this, this.options); // 1.使用options中的主题类初始化主题实例
// 2.增加必需模块
this.keyboard = this.theme.addModule('keyboard');
this.clipboard = this.theme.addModule('clipboard');
this.history = this.theme.addModule('history');
this.theme.init(); // 3.初始化主题,这个方法是模块渲染的核心(实际的核心是其中调用的addModule方法),会遍历配置的所有模块类,并将它们渲染到DOM中
...
}
Когда Quill инициализируется, он будет использоватьexpandConfigМетод расширяет входящие параметры и добавляет такие элементы, как классы темы, для инициализации темы. (Также будет тема BaseTheme по умолчанию без настройки темы)
После вызова экземпляра субъектаaddModuleМетод монтирует встроенные необходимые модули в экземпляр темы.
Последний вызов экземпляра субъектаinitметод для рендеринга всех модулей в DOM. (Принцип будет подробно описан позже)
Если снег является темой, на этот раз над редактором появится панель инструментов:
Если тема пузырька, то была избрана в тексте, панель инструментов появится плавающее поле:
Далее мы возьмем модуль панели инструментов в качестве примера, чтобы подробно представить принцип загрузки и рендеринга модуля Quill.
Загрузка модуля панели инструментов
Взяв в качестве примера снежную тему, настройте следующие параметры при инициализации экземпляра Quill:
{
theme: 'snow',
modules: {
toolbar: [['bold', 'italic', 'strike'], ['link', 'image']]
}
}
This.theme, полученная в методе конструктора Quill, является экземпляром класса SnowTheme, выполнитеthis.theme.init()Метод вызывает метод init своего родительского класса Theme, который находится вcore/theme.jsдокумент.
init() {
// 遍历Quill options中的modules参数,将所有用户配置的modules挂载到主题类中
Object.keys(this.options.modules).forEach(name => {
if (this.modules[name] == null) {
this.addModule(name);
}
});
}
Он будет проходить по всем модулям в параметре options.modules и вызывать метод addModule BaseTheme, который находится вthemes/base.jsдокумент.
addModule(name) {
const module = super.addModule(name);
if (name === 'toolbar') {
this.extendToolbar(module);
}
return module;
}
Этот метод сначала выполнит метод addModule своего родительского класса для инициализации всех модулей.Если это модуль панели инструментов, дополнительная обработка будет выполняться в модуле панели инструментов после инициализации модуля панели инструментов, в основном для создания значков и привязки клавиш быстрого доступа к гиперссылкам. .
Вернемся и посмотрим на BaseThemeaddModuleметод, который模块加载的核心.
Этот метод был замечен ранее, когда мы представили инициализацию Quill, и он вызывается, когда загружаются три встроенных обязательных модуля. На самом деле через этот метод загружаются все модули, поэтому необходимо изучить этот метод, который находится вcore/theme.js.
addModule(name) {
const ModuleClass = this.quill.constructor.import(`modules/${name}`); // 导入模块类,创建自定义模块的时候需要通过Quill.register方法将类注册到Quill,才能导入
// 初始化模块类
this.modules[name] = new ModuleClass(
this.quill,
this.options.modules[name] || {},
);
return this.modules[name];
}
Метод addModule сначала вызовет метод Quill.import.导入模块类(Его можно импортировать только в том случае, если он был зарегистрирован методом Quill.register).
потом初始化该类, и смонтировать его экземпляр в переменную-член modules класса темы (эта переменная-член уже имеет экземпляр встроенного необходимого модуля).
Взяв в качестве примера модуль панели инструментов, класс панели инструментов инициализируется в методе addModule, расположенном вmodules/toolbar.jsдокумент.
class Toolbar {
constructor(quill, options) {
super(quill, options);
// 解析modules.toolbar参数,生成工具栏结构
if (Array.isArray(this.options.container)) {
const container = document.createElement('div');
addControls(container, this.options.container);
quill.container.parentNode.insertBefore(container, quill.container);
this.container = container;
} else {
...
}
this.container.classList.add('ql-toolbar');
// 绑定工具栏事件
this.controls = [];
this.handlers = {};
Object.keys(this.options.handlers).forEach(format => {
this.addHandler(format, this.options.handlers[format]);
});
Array.from(this.container.querySelectorAll('button, select')).forEach(
input => {
this.attach(input);
},
);
...
}
}
Когда модуль панели инструментов инициализируется, сначала будет проанализирован параметр modules.toolbar, а вызовaddControlsМетод генерирует кнопки панели инструментов и раскрывающиеся списки (основной принцип заключается в обходе двумерного массива и вставке их на панель инструментов в виде кнопок/раскрывающихся списков) и связывает с ними события.
function addControls(container, groups) {
if (!Array.isArray(groups[0])) {
groups = [groups];
}
groups.forEach(controls => {
const group = document.createElement('span');
group.classList.add('ql-formats');
controls.forEach(control => {
if (typeof control === 'string') {
addButton(group, control);
} else {
const format = Object.keys(control)[0];
const value = control[format];
if (Array.isArray(value)) {
addSelect(group, format, value);
} else {
addButton(group, format, value);
}
}
});
container.appendChild(group);
});
}
Таким образом, модуль панели инструментов загружается и отображается в редакторе форматированного текста для облегчения операций редактора.
Теперь подведем итоги процесса загрузки модуля:
- Отправной точкой загрузки модуля является метод init класса Theme, который загружает все модули, сконфигурированные в параметре option.modules, в модули переменных-членов класса темы и объединяет их со встроенными требуемыми модулями;
- Метод addModule сначала импортирует класс модуля с помощью метода импорта, а затем создает экземпляр модуля с помощью нового ключевого слова;
- При создании экземпляра модуля выполняется метод инициализации модуля и выполняется определенная логика модуля.
Ниже приведена диаграмма взаимосвязи между модулем и экземпляром редактора:
Суммировать
В этой статье на двух примерах кратко представлен метод настройки модуля Quill, чтобы у каждого было интуитивное и предварительное представление о модуле Quill.
Затем на простом примере модуля статистики символов показано, как разработать собственный модуль Quill для расширения функций редактора форматированного текста.
Наконец, проанализировав процесс инициализации Quill, шаг за шагом рассмотрим механизм загрузки модуля Quill и подробно разработаем процесс загрузки модуля панели инструментов.
Присоединяйтесь к нам
МыКоманда DevUIДобро пожаловать и присоединяйтесь к нам, чтобы создать элегантную и эффективную систему человеко-машинного проектирования/исследований и разработок. Электронная почта для приема на работу:muyang2@huawei.com.
Текст/DevUI Кагол