Я считаю, что многие студенты, даже если они не были знакомы с областью редактирования форматированного текста, должны были слышать высказывание о том, что «редактирование форматированного текста — это тянькэн, не трогайте его» — да, редактирование форматированного текста — это тянькэн. , ноSlateможет помочь вам очень хорошо. Далее будет представлена сложность редактирования форматированного текста и решение Slate.
задний план
Существует очень тонкая разница между редактированием форматированного текста и обычной фронтенд-разработкой: в этой области самые популярные решения имеют тенденцию быть довольно тяжелыми. Почему облегченные редакторы не стали мейнстримом в сообществе фронтендов, которое всегда уважало [чем легче, тем лучше]? Это начинается с принципа реализации редактора.
В браузере принципы реализации форматированного редактирования текста можно условно разделить на следующие три типа:
- существует
<textarea>
Различные стили расположены сверху. Это то, что использовала ранняя система комментариев Facebook. - Реализуйте свой собственный движок компоновки, даже мигающий курсор пропускается
<div>
контроль. Это то, что использует Документы Google. - Используйте собственный режим редактирования ContentEditable браузера. Это то, что использует подавляющее большинство существующих редакторов форматированного текста.
Из трех решений первое трудно поддерживать даже выделение жирным шрифтом, курсивом и другие операции, и от него в основном отказались; у второго огромная рабочая нагрузка, и только такие гиганты, как Google и Microsoft, которые могут создавать свои собственные браузеры, могут хорошо играть . , для последнего, если вы не понимаетеcontenteditable
, вы можете открыть любой веб-сайт в его<body>
Добавьте этот атрибут в тег, и посмотрите, как он превращается в шикарный редактор 😀 Кажется, этот способ гораздо надежнее двух предыдущих, браузер уже обработал сочетания клавиш, стек отмен, Курсор, метод ввода, совместимость. .. Очень внимательный!
Смерть контентаEditable
Она была в то время слишком молода, чтобы знать, что всем подаркам судьбы уже втайне назначена цена.
- Цвейг, "Разлученная королева"
Бесплатных обедов не бывает, и ContentEditable не исключение. Автор Medium Editor написал статью, которая знакомитСтрашная вещь о ContentEditable. Критику в статье можно свести к одному предложению, структуре данных и поведению ContentEditable.отсутствие последовательности.
Например, к предложению [Добро пожаловатьДевятнадцатый национальный конгресс], следующие HTML-представления полностью эквивалентны:
<!--正常-->
<p>喜迎<b>十九大</b></p>
<!--分离的 b 标签-->
<p>喜迎<b>十</b><b>九大</b></p>
<!--嵌套的 b 标签-->
<p>喜迎<b><b>十九大</b></b></p>
<!--空的 b 标签-->
<p>喜迎<b>十</b><b></b><b>九大</b></p>
<!--span 代替 b 标签-->
<p>喜迎<span style="font-weight: bold">十九大</span></p>
Хотя они выглядят одинаково, есть существенные различия в их поведении при редактировании. А при использовании ContentEditable,Браузеры часто автоматически вставляют эти спам-теги.
В качестве другого примера, для предложения [Добро пожаловать на 19-й национальный конгресс Коммунистической партии Китая] простая операция разрыва строки может дать следующие результаты:
<p>喜迎<br/>十九大</p> <!--插入 br 标签-->
<p>喜迎</p></p>十九大</p> <!--分割 p 标签-->
Разные браузеры ведут себя по-разному даже для простых разрывов строк. Таким образом, документ, отредактированный в Chrome, может иметь ошибки после открытия в Firefox для продолжения редактирования, и эти ошибки не являются простой проблемой стиля.Это порочная ошибка, которая разрушает структуру данных.
В сообществе много так называемых [сверхлегких редакторов], и они представляют собой почти просто прославленную оболочку ContentEditable. Этот тип редактора в основном полностью зависит от собственного поведения браузера и не принимает во внимание разрушение структуры данных ContentEditable, на их основе очень сложно реализовать расширенные функции редактирования. Если вы выбираете их с идеей «легкие вещи красивее», подумайте дважды, прежде чем принять решение.
Это приложение, библиотека классов или фреймворк?
Еще одна неприятная проблема в области редактирования форматированного текста — позиционирование редактора. Вообще говоря, различные проекты, с которыми связывались в области переднего плана, представляют собой не что иное, как следующие три:
Приложение Приложение
Приложения обычно относятся к проектам, которые включают интерфейс и логику взаимодействия, такие как различные фоновые системы управления.
библиотека классов
Библиотека классов предоставляет пользователям API для разработки приложений, ноНе влияет на структуру кода приложения, такие как jQuery и React:
jQuery: The Write Less, Do More, JavaScript Library
React is a JavaScript library for building user interfaces.
Возможно, у многих студентов есть предубеждения против React, поэтому я еще раз подчеркну это здесь.Сам React — это всего лишь слой представления, который необходимо объединить со многими библиотеками классов, прежде чем его можно будет использовать для разработки приложений.
Рамочная структура
Фреймворк также предоставляет API, но он очень навязчив к коду приложения, требуя от пользователей следовать пути фреймворка,Предоставьте код для запуска фреймворка. И Vue, и Angular являются типичными фреймворками:
Vue.js - The Progressive
JavaScript FrameworkAngularJS — Супергеройский JavaScript MVWFramework
Итак, что из вышеперечисленного является редактором форматированного текста? Каждый проект редактора скажет, что он позиционируется как Editor, но является ли Editor приложением, библиотекой классов или фреймворком? Многие редакторы, ориентированные на нестандартные решения, интегрировали многие стили и логику взаимодействия.уже приложение.
Проблема здесь в том,Настройка приложения — худшее. Поэтому, когда необходимо настроить другой опыт редактирования, многие готовые редакторы трудно удовлетворить потребности за счет простой настройки. В это время часто приходится использовать различные приемы и хитрости, либо изучать набор корявых подключаемых механизмов самого редактора.
Такие фреймворки, как Vue и Angular, славятся простотой использования. Итак, существует ли такая структура в области редактирования форматированного текста? Да, и Слейт не первый. Учащиеся, знакомые с редакторами, могут знать, что FacebookDraft.js— это одна из таких сред редактирования, которая позволяет вам настраивать ваш редактор с помощью стека React. Теперь, когда Draft.js великолепен, как Slate может сравниться с ним? А что касается различных проблем ContentEditable, описанных выше, как их решает Slate? Давайте взглянем.
Представляем сланец
Slate — это не приложение-редактор, а мощная платформа для управления форматированными текстовыми данными на прочной основе React и Immutable.Внедрение редактора форматированного текста на основе Slate эквивалентно разработке обычного веб-приложения с использованием React (уровень представления) + Immutable (уровень данных).На следующем рисунке показана архитектура редактора на основе Slate.Поток данных очень прост и понятен:
На рисунке панель инструментов панели инструментов на левом слое просмотра и различные узлы в редакторе являются чистыми компонентами React, а слой модели справа использует большую поддержку, предоставляемую Slate. Ниже мы кратко представим несколько ключевых ролей в этой архитектуре.
Immutable, самая идеальная структура данных на данный момент
Мы знаем, что свойства JS-объектов можно назначать по желанию, то есть mutable — переменная. С другой стороны, неизменяемые типы данных не допускают произвольного назначения, и каждый раз при изменении неизменяемого API будет создаваться новая ссылка.
Это не кажется чем-то большим, и это ничем не отличается от создания полной копии данных для каждой модификации. Но сила Immutable в том, чтоОдни и те же части полностью разделены между разными ссылками. Это также означает, что для сложного дерева документов, основанного на Immutable,Даже если изменится только один конечный узел, будет сгенерировано новое дерево, но все содержимое этого нового дерева будет общим с исходным деревом, за исключением этого конечного узла..
Какое это имеет отношение к редактированию форматированного текста? Мы знаем, что [отмена] редактора на самом деле очень сложная функция.Многие редакторы, которые настроили функцию отмены, склонны к несогласованным состояниям до и после отмены. Но с Immutable каждое редактирование генерирует совершенно новое состояние редактора, простоЛегко отменять и повторять операции, просто переключаясь между различными состояниями. Более того, Immutable также полностью поддерживает сложную вложенность для выражения древовидной структуры документов. Можно сказать, что Immutable естественным образом подходит для уровня модели, реализующего форматированное редактирование текста. В Slate и Draft.js форматированные текстовые данные представляют собой слой инкапсуляции Immutable, который поддерживает операции отмены без дополнительного кодирования. Большой плюс Slate по сравнению с Draft.js в этом отношении заключается в том, что онПоддержка вложенных структур данных, который обеспечивает хорошую поддержку редактирования сложного содержимого, такого как таблицы.
React, пока что самый подходящий слой просмотра
Говоря об Immutable, нельзя не упомянуть React, в настоящее времяImmutable.jsЭта JS-библиотека неизменяемых данных реализована самой Facebook, и цель введения Immutable в начале — не отменить, а оптимизировать производительность приложений React. Можно сказать, что Immutable и React имеют естественное молчаливое понимание.
Итак, зачем нам нужен React? В настоящее время почти для всех редакторов, кроме Slate и Draft.js, при настройке узлов редактирования (таких как формулы, диаграммы и т. д.) функция. Такой подход не является оптимальным с точки зрения стоимости и эффективности обучения.
Представьте, еслиВесь контент редактирования в редакторе может быть реализован в виде компонентов React (таких как компоненты Heading для заголовков, компоненты Paragraph для абзацев и т. д.), так что порог редактирования форматированного текста будет все еще таким высоким? Сопоставление неизменяемых данных с отдельными компонентами React — проверенный шаблон, протестированный во многих веб-приложениях. При такой архитектуре сложные проблемы ContentEditable также могут быть решены очень хорошо: просто добавьте компоненты React.contentEditable
свойств, а затем для различных нажатий клавиш, щелчков и других событийpreventDefault
, фреймворк определяет преобразование событий в Immutable и, наконец, генерирует новое состояние для запуска перерисовки по мере необходимости!
По этой схеме для реализации редактора больше не требуются специалисты, владеющие DOM, и сложность значительно снижается. Даже рядовые разработчики вроде автора этой статьи, которые только знакомы с React и имеют больше года опыта во фронтенде, способны разрабатывать свои собственные редакторы. Вот немного личных вещей:
В области редактирования форматированного текста React + Immutable, который изменяет состояние с глобальной степенью детализации, а затем обновляет компоненты по запросу, более выгоден, чем Vue, который обновляет компоненты на детальном уровне на основе отслеживания зависимостей. То, как Vue напрямую мутирует данные, не способствует реализации отмены и отката в принципе, а API функционального компонента VNode не так интуитивно понятен и прост в использовании, как React (Vue 2.5 улучшился, но пробел все еще существует). В настоящее время в сообществе Vue нет аналогичного фреймворка.Этот сценарий также является яркой точкой стека React по сравнению с Vue.
Однако и Draft.js, и Slate реализуют поддержку React. Хотя API Slate для пользовательских узлов немного удобнее, это тоже не решающее преимущество. Так что же такого особенного в Slate?
Slate, самый гибкий контроллер
Из предыдущего введения мы увидели, что в Draft.js появилось довольно много инноваций. Итак, что делает Slate уникальным?
В Draft.js есть Immutable в качестве модели и React в качестве представления, но в процессе его использования для реализации редактора вы можете почувствовать, что бремя все еще немного тяжелое по сравнению с общей разработкой приложений или чего-то не хватает. Ну, это может быть Контроллер, с которым вы знакомы.
Даже в сегодняшних интерфейсных колесах MVC, архитектура UI-приложений, не устареет, а развилась в архитектуру MVVM или даже M-V-Whatever. Приложение редактора также является приложением пользовательского интерфейса,Нам также нужен механизм для соединения модели и представления..
Это может быть не то место, где Draft.js блистает, его API преобразования документов сложен в использовании, и есть больше ограничений на редактирование EditorState. С другой стороны, Slate обеспечивает более гибкую концепцию соединения модели и представления. Давайте кратко представим поток обработки, когда операции редактирования происходят в Slate:
- Пользователь нажимает клавишу в узле, где находится курсор редактора, чтобы инициировать событие.
- В соответствии со значением ключа распределяются различные изменения, такие как разрыв строки, полужирный шрифт и т. д.
- Change Измените состояние и создайте новое состояние.
- После того, как новое состояние проверено схемой, оно отображается в редакторе, и соответствующий узел обновляется по мере необходимости.
Основной механизм всего процесса можно обобщить в виде формулы:state.change().change()
, Change — очень элегантный API, все преобразования реализуются через объекты Change. Например, если пользователь вставляет текст, а затем удаляет другой абзац, изменения в документе можно абстрагировать следующим образом:
state.change().insertText().deleteBlock()
Каждая операция связана! В сценарии совместного редактирования операции от разных пользователей фактически могут быть отнесены к таким цепным обращениям к State, что также позволяет реализовать совместное редактирование на базе Slate. С другой стороны, API в каждом вызове цепочки Change может быть реализован как чистая функция, а затем передан через Slate.call
API связан, что также позволяет писать собственные изменения и добавлять модульные тесты.
Этот элегантный способ обработки операций редактирования упрощает для Slate подключение моделей и представлений для реализации сложных операций с форматированными текстовыми данными. Кроме того, Slate поддерживает настраиваемые правила проверки схемы для состояний.Вы можете добавить некоторые правила проверки в форме [первый узел должен быть узлом заголовка] или [узел изображения должен содержать атрибут src] и фильтровать аномальные данные.
Конечно, в Slate нет концепции контроллера, но на самом деле операция Change редактирования форматированного текста на основе Slate чем-то похожа на опыт написания логики контроллера в традиционных приложениях MVC. Другими словами, Slate снижает сложность написания сложной логики операций до уровня написания функций Change. На данный момент архитектура Slate очень проста в использовании.
Суммировать
Slate — восходящая звезда в области редактирования форматированного текста. Однако всего за год с момента его запуска количество участников сообщества приблизилось к количеству участников Draft.js и даже Vue, достигнув уровня 100. При этом его Issue и PR-обработка более своевременны, чем Draft.js, автор более открыт для новых идей, а итерация более активна.
Многие из основных функций Slate заимствованы из других отличных проектов редакторов, таких как уровень неизменяемых данных и концепция фреймворка из Draft.js, концепции Schema и Change из ProseMirror и т. д. Хотя многие из его основных моментов не уникальны сами по себе, они делают это на макроуровне (звучит немного близко к Vue?). В настоящее время он все еще находится в стадии быстрой итерации.Для студентов, которые заинтересованы в участии, есть много возможностей стать участниками.