передняя часть Seewo ENOW
Официальный сайт компании:CVTE (Гуанчжоу CVTE)
Команда: enow team центра программных платформ Seewo для будущего образования в рамках CVTE
Автор этой статьи:
предисловие
Эта статья начинается с чистого фронтенда, поэтому она не будет затрагивать подобныеflash
Или операция копирования и вставки, которая пропускает проверку безопасности браузера, например подключаемые модули, полностью основана на ограничениях безопасности в браузере и некоторых «волшебных трюках» для достижения относительно полной функции копирования-вставки.
Эта статья начнется с функции копирования и вставки самого браузера, познакомит вас с реализацией функции копирования и вставки, сравнит реализацию нескольких форматированных текстовых документов и с учетом различных ограничений браузера, как реализоватьJSON-MODEL
Данные и применяются к буферу обмена класса форматированного текста.
Важность копирования и вставки
ориентированныйGoogle
а такжеnpm
трудящихся-мигрантов не могут не пониматьCV
Насколько хорош Дафа, и копирование и вставка уже давно стали частью нашей повседневной работы и жизни. Фактически, для обработки текста важность функции копирования и вставки совершенно невообразима.
И в коде нередко используются элементы формы. В элементах формы, полях ввода и других носителях ввода мы можем не знать внутреннюю реализацию копирования-вставки:
Например, скопировать картинку извне и вставить в поле ввода, но добиться этого нельзя, а текст можно? Как реализовать вставку внешнего стиля текста, см.word
тот самый документ? Как копировать и вставлять изображения в форматированный текст? Как настроить нашу функцию копирования и вставки?
копипаст тройка
Здесь нам нужно сначала понять три концепции:MIME,DataTransfer,clipboardEvent:
Тип носителя (MIME)
На самом деле, когда мы находимся в элементе формы, таком какinput
,textarea
Полное копирование и вставка реализованы в браузере, что вызывает возможности браузера по умолчанию.
Сначала нам нужно понять, что такое MIME:
Тип мультимедиа (часто называемый многоцелевыми расширениями почты Интернета или типами MIME) — это стандарт, используемый для представления характера и формата документа, файла или потока байтов;
MIME
Структура на самом деле очень проста: она состоит из типа и подтипа, а середина двух строк'/'
разделенная композицияtype/subtype. Пробелы не допускаются.
Общие типы MIME:text/plain,text/html,image/png,application/json
Ждать;
Например, мы пишемscript
илиstyle
При определении:
<style type="text/css"></style>
<script type="text/javascript"></script>
Или когда вы обычно запрашиваете внутренний интерфейс:
Те, кто знаком со спецификациями интерфейса или занимался внутренними службами, должны знать, чтоcontent-type
Определение слова end на самом деле тесно связано с анализом back-end программы, при отладке интерфейса часто появляетсяcontent-type
Несоответствия с отправленными данными, например, что нужно серверной частиapplication/json
данные, то если переданоapplication/x-www-form-urlencoded
В формате обычно возвращается код состояния ошибки. В это время интерфейс должен бытьcontent-type
Проведите соответствующую обработку данных.
Конечно, есть и некоторые специальные реализации:Content-Type: multipart/byteranges; boundary=xxxx
Для информирования браузера о том, что данные разделены на несколько частей для достижения функции, аналогичной загрузке аудио- и видеосегментов;
Другими словами, браузер хочет знать, к какому типу данных относятся ваши данные, и какой анализ или обработка загрузки ему требуется (например, анализ в медиафайл или файл документа, который обычно загружается как ресурс). .MIME
быть информированным;
В процессе копирования и вставки, по сути, также необходимо пройтиMIME
провести соответствующий анализ.
DataTransfer
На самом деле, это объяснение на MDN не является полным, за исключениемdrag events
также доступен вpaste,copy,cut
И другие события по приобретению. Я предпочитаю документ "мобильные данные" может быть использованDataTransfer
определять.DataTransfer
Существует множество свойств и методов, но большинство из них находятся вdrag
генерируются или могут быть только использованы. Напримерfiles
относятся только кdrag
Событие, если операция перетаскивания не включает в себя файлы перетаскивания, атрибут является пустым номером:
Поэтому мы просто сосредоточимся наitemsэто свойство.items
даData
объект;
Также есть пара методов:
- setData(формат, данные) используется для установки содержания;
- getData(формат) получить контент;
clipBoardEvent
clipboardEvent
является общим событием буфера обмена, поддерживаемым браузером. включеныpaste、cut、copy
связанные события;
Нам нужно только обратить внимание на эти два свойства при копировании и вставке:
type: описывает тип триггера события;
clipboard: ОдинDataTransfer
объект;
Реализация браузера по умолчанию
В браузере обычно при копировании и вставке используется стандартный формат MIME, обычно используемый браузерами (из скриншотов MDN):
Например, вinput
а такжеtextarea
Только получать в копировании и вставкеtext/plain
изMIME
Тип, это также может быть текстовый формат по умолчанию, который будет поддерживать все программное обеспечение (не сталкивался с тем, что не поддерживает этот формат).
Конечно, если вашinput type
Установить какfile
Вы можете выбрать поддержку других типов файлов, здесь особо нечего обсуждать.
сцена с расширенным текстом
В форматированном тексте, в дополнение к обычному тексту, которыйtext/plain
В дополнение к этому типу, как правило, необходимо поддерживать два другихMIME
тип, соответственноtext/html
а такжеimage/png
(Здесь просто относится к копированию и вставке)
текст/html:
Например, чтобы реализовать функцию: fromword
Такие документы, как копирование и вставка фрагмента текста, требуют согласованности стиля и форматирования, что должно быть общей чертой форматированного текста;
В это время, если мы непосредственно получимtext/plain
В этом случае можно получить только соответствующую текстовую версию. Вот когда нам нужно получитьtext/html
тип текста. Стоит отметить, что обычные текстовые редакторы (word,ppt
, документы Kingsoft...), полученные данные не в стандартном формате html или содержат большое количество избыточных данных. В настоящее время нам может потребоваться взять на себя инициативу по очистке данных и оставить только те данные, которые нам нужны. . . . Как правило, после получения данных вы можете использовать обычный метод для очистки избыточных данных.ueditor、wangeditor
Соответствующую обработку данных можно увидеть в обычном форматированном тексте.
изображение/png:
Скопируйте изображения, как правило, копируйте и вставляйте снаружи;
текущая сцена
Сначала мне нужно сделать что-то вродеPPT
Реализация функции копирования и вставки в документе включает в себя копирование текста и изображений и вставку их на нашу страницу, во-вторых, нам необходимо поддерживать другие внутренне определенные элементы, и, наконец, нам нужно поддерживать кросс-таблицу или даже кросс-браузерность на нашей странице. Последовательное копирование-вставка взаимодействия;
и из-заJSON
данные иhtml
Данные не подключены.Например,в обычном текстовом редакторе копирование напрямую получается в основном напрямую.html
данные; и в текущем сценарии, поскольку использованиеMVVM
Причина в рамках, мы ставим всеdom
преобразован в единыйmodel
Данные, поэтому данные, которые вы копируете, должны быть обработаны отдельно и не могут быть непосредственно вставлены в любой богатый текст.
Итак столкнулся со следующими проблемами:
1. Ограничения безопасности буфера обмена браузера
Браузеры имеют строгие ограничения безопасности в отношении буфера обмена: прямое чтение содержимого буфера обмена запрещено, если только не используется предложенныйnavigator.clipboard.readText / navigator.clipboard.read
Для запросов разрешений пользователи могут читать сразу после того, как они передают инициативу, но это рискованно. Прежде всего, это предложение все еще находится в стадии разработки.draft
Конечно, вероятность прохождения этапа очень велика, ведь для того, чтобы заменитьdocument.execCommand
Существует, но наша программа должна быть обратно совместима. Во-вторых, если пользователь активно запрещает этот метод, с последующей операцией вставки все равно будут проблемы. Следовательно, он должен эксплуатироваться по существующим стандартам;
Google Slides
Реализовано на:
- Активно спрашивайте пользователя, следует ли устанавливать подключаемый модуль, и пропускайте этот уровень ограничений безопасности для подключаемого модуля;
- Без установки, в
safari
Нажмите «Вставить», и вы снова увидите всплывающую маленькую кнопку, потому чтоsafari
Возможность настройки меню;
2. Дилемма настройки контекстного меню
И на самом деле, в большинстве этих сценариев контекстное меню также настраивается. Вообще говоря, мы можем напрямую вызвать контекстное меню для копирования и вставки в соответствии с поведением браузера, но если вы хотите настроить меню, вы, конечно, можете отслеживатьcontextMenu
событий, а затем активно предотвращать поведение по умолчанию, например документацию Tencent илиGoogle Slides
Сюда. Однако некоторые действия браузера скрыты или даже не могут быть активизированы: например, копирование и вставка. Некоторые веб-документы даже нажимают кнопку вставки в меню, и сразу появляется подсказка, надеясь, что пользователь может вставить напрямую с помощью сочетания клавиш, что, конечно, очень античеловечно.
Основываясь на двух вышеприведенных пунктах, вам необходимо иметь собственный набор данных памяти, предоставлять данные в буфер обмена и контекстное меню, а затем активно обновлять при необходимости.clipboard
, чтобы объединить вставленные данные памяти системы и данные внутренней памяти.
Вот трюк, который вы можете использоватьdocument.execCommand('copy/cut')
активно обновлятьclipboard
данные в. Когда вы щелкаете правой кнопкой мыши для копирования, если вам нужно активно обновлять данные в буфер обмена, вы можете активно вызывать и получатьcut/copy
брошенное событиеclipboardData
, затем используйтеsetData
, который полезен для объединения внутренних и внешних данных и управления потоком данных между вкладками.
private bindCopy = (e) => {
......
console.error('copy');
e.preventDefault();
this.duplicate.attemptToCopy(e, false);
};
// Duplicate类
/**
* 复制/剪切
* @param e ClipboardEvent
* @param isCut 是否为剪切
* 1. 主动快捷键复制粘贴
* 2. 右键菜单点击复制(不存在clipboardData对象)
* 3. 主动塞入自定义数据
*/
public attemptToCopy(e: ClipboardEvent | null, isCut = false) {
this.isCutCommand = isCut;
if (e && e?.clipboardData) {
const clipboardData = this.updateStash();
clipboardData && this.updateClipboard(e, clipboardData);
} else {
this.autoCopy();
}
}
/**
* 自动拷贝
* 1. 支持execCommand时,相当于复制后重新走一次addEventListener('copy')
* 这时候可以拿到e.clipboardData对象,可以执行上面的updateStash
* 好处:可以在copy里setData,设置标志位;缺点:execCommand有风险为被废除
* 2. 不支持时,使用writeText
* 好处:降级处理;缺点:无法设置特殊MIME,只能在getData('text/plain')里判断
*/
public autoCopy() {
if (!document.execCommand(this.isCutCommand ? "cut" : 'copy')) {
const clipboardData = this.updateStash();
clipboardData && navigator.clipboard.writeText(JSON.stringify(clipboardData));
}
}
Конечно, я сделал здесь небольшую совместимость, все-такиdocument.execCommand
Метод является устаревшим состоянием. курс использованияnavigator.clipboard.write
это тоже хорошо.
3. Смерть пользовательских типов MIME
Мыclipboard
то естьDataTransfer
Возможен прямой доступ к нашим внутренним данным,
Например, мы даем специальную метку, напримерtext/copy, то есть определяемMIME
тип, то в следующий раз мы можем напрямую передатьgetData('text/copy')
Получить, разве это не хорошо?
Это как сказать стандартMIME
Тип - твердая валюта.После стольких лет все регионы (производители браузеров и системного софта) ее поддерживают, а также имеют свои методы обмена (универсальныеMIME
синтаксический анализ), в то время как наши собственные определенныеMIME
Но это цифровая валюта, возникшая из ниоткуда, она точно не признается рынком и может использоваться только внутри страны. Аналогично: в общем, это вполне осуществимо. Но это не стандарт в конце концовMIME
Тип, кросс-браузерная загрузка невозможна. То есть некоторые крайние сценарии неприемлемы.
Итак, почему мы должны устанавливать свои собственныеMIME
Шерстяная ткань? первый генералMIME
Кромеtext/plain
, остальные типы будут активно добавлять данные, необходимые для типа, напримерtext/html
Если это так, он добавит соответствующие в начале и в концеxml
Данные формата, в то время как другие были упомянуты ранее, будут проходить один разMIME
парсинг, для стандартного, но специальногоMIME
Формат может иметь некоторые специальные добавленные данные или операции синтаксического анализа.
Во-вторых, кроссбраузерность я пока только виделtext/plain
а такжеtext/html
Можно передавать данные, а остальное будет фильтроваться... Но если задать прямоtext/plain
Да, все скопированные внутренние данные будут отображаться при внешнем событии вставки. Если это обычные текстовые данные, все в порядке. Если это внутренние сохраненные отформатированные данные, это заставит пользователей чувствовать себя странно.
Затем первоначальная доработка заключается в использовании специальногоMIME
тип + одинtext/html
, который может анализировать внутренние данные.
Идея очень хорошая, но в этот раз вы столкнетесь с другой проблемой: для некоторых текстовых редакторов основная информация, получаемаяtext/html
Сделайте еще один уровень анализа, тогда ваши данные будут доступны другим. Для этого, если это копирование во внешнюю вставку, извините, нет хорошего способа, потому что вы хотите сохранить единообразие данных и кросс-браузерное поведение. Если это внутренний редактор, то он будет сопоставлен, а если это внутренние данные, то они будут отфильтрованы напрямую.
Конечно, могут быть некоторые особые случаи, такие как внешнее копированиеsvg
картинки, на самом делеsvg
даxml
форматированные текстовые данные, маленькиеsvg
Картинка, конечно, хороша, если большая, то нет гарантии, что браузер не зависнет. тогда вам может понадобитьсяtext/plain
Кстати, сделайте предварительный вывод...
Конечно, если вам не нужно иметь дело с кросс-браузерностью, то вам не нужно особых проблем, просто сохраните собственный тип MIME.
Вообще говоря, когда мы получаем содержимое буфера обмена, мы сначала оцениваем внутренние данные, то есть настраиваемый тип MIME, затем тип изображения и, наконец, тип простого текста;
import { SPEC_MIME } from "../util/variable";
class PasteHelper {
// 获取img数据
// 网上图片直接右键复制: [text/html, image/png]
// ppt/截图工具 [image.png]
// ppt文字:[text/plain,text/html,text/rtf,image/png]
// RTF: 微软下的跨文本格式
// https://zh.wikipedia.org/wiki/RTF
public getImgTransData(e: ClipboardEvent) {
if (!e.clipboardData?.items?.length) {
return false;
};
const transferDatas = Array.from(e.clipboardData.items);
const isText = transferDatas.find(c => c.type === 'text/rtf');
// 需要处理视频类的情况,返回img,但是getAsFile为null
if (!isText) {
const imgTransData = transferDatas.filter(c => c.kind === 'file' && c.type.indexOf('image') === 0)[0];
if (!imgTransData) {
return false;
} else {
const imgFile = imgTransData.getAsFile();
if (imgFile) {
return imgFile;
}
}
};
return false;
}
/**
* 判断是否为内部数据
* 降级SPEC_MIME -> htmlData(跨浏览器) -> plainText(execommand不可用,走writeText)
* @param e ClipboardEvent
*/
public getInnerData (e: ClipboardEvent) {
const innerData = e.clipboardData?.getData(SPEC_MIME);
......
}
// 获取纯文本,空白字符过滤
public getPlainText (e: ClipboardEvent) {
// 过滤特殊字符,给予空字符串
const reg = /[\0-\x08\x0B\f\x0E-\x1F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
let text = e.clipboardData?.getData('text/plain') || "";
text = text.replace(reg, " ");
return text ?? false;
}
}
export default new PasteHelper();
4. Ад — это совместимость платформ
Вообще говоря, если мы скопируем и вставим, мы надеемся, что сможем следоватьword、ppt
Подождите, пока взаимодействие с локальным приложением не станет согласованным. Однако воображение полно, а реальность очень худа.
Под несколькими платформами уровень поддержки разный, и даже при реализации получаются совершенно разные данные.
В следующей таблице показаны полученные данные, скопированные из внешнего источника и вставленные во внутренний:
внешний источник | текст | картина | текстовое окно | Аудио и видео |
---|---|---|---|---|
веб-страница (обычная) | служба поддержки | служба поддержки | преобразовать в текст | не поддерживается |
google slide | служба поддержки | не поддерживается | преобразовать в текст | не поддерживается |
Документация Тенсент | служба поддержки | не поддерживается | преобразовать в текст | не поддерживается |
офис ppt (веб) | служба поддержки | не поддерживается | не поддерживается | не поддерживается |
Документация Kingsoft (веб-версия) | служба поддержки | не поддерживается | не поддерживается | не поддерживается |
офис (ppt/excel) | служба поддержки | служба поддержки | преобразовать в текст | преобразовать в изображение |
wps | служба поддержки | не поддерживается | не поддерживается | не поддерживается |
keynote | служба поддержки | служба поддержки | преобразовать в текст | преобразовать в изображение |
numbers | служба поддержки | служба поддержки | преобразовать в текст | не поддерживается |
окна (система) | служба поддержки | не поддерживается | - | не поддерживается |
уос (система) | служба поддержки | преобразовать в текст | - | преобразовать в текст |
макинтош (система) | служба поддержки | служба поддержки | - | преобразовать в текст |
Google Slides
, документы Tencent и т. д.web
Приложение не поддерживает копирование картинок и требует отдельного разбораtext/html
Картинки в данных, то есть необходимость парсинга строк, реально сделать;
документ Кингсофт,office
Ждатьweb
Причина, по которой приложения не поддерживают текстовые поля и текст, заключается в том, что эти приложения используют внутренние протоколы, а мы обычно не ориентируемся на специальные протоколы (MIME
) сделать обработку;windows
Система не поддерживает копирование и вставку картинок и аудио и видео.После тестирования под этой системой можно получить только обычный текст;
В такой ситуации можно только обнять бедро отца продукта и сказать: Чен Ци не может этого сделать...
5. Ахиллесова пята обработки медиафайлов
Основываясь на доверии к внутренним данным, вы можете сначала скопировать данные, сериализовать их и поместить в наш индивидуальныйMIME
В типе будет нормально вытащить его и десериализовать в следующий раз.
Однако вначале наши продукты делали специальную обработку мультимедийных файлов (аудио, видео, картинки): при загрузке на нашу страницу они просто конвертировались вblob
, сохраните его в памяти, а затем загрузите в облако для следующей синхронизации. Такой подход может в определенной степени улучшить пользовательский опыт, ведь после загрузки нет необходимости загружать в облако.
Но здесь есть недостаток: при перекрестных вкладках, если предыдущая вкладка закрыта, то она привязывается кblob
Ссылка не работает, потому чтоblob
Адрес памяти или ссылки сохраняется на предыдущей вкладке, но если вы измените его в это время, сфера влияния станет шире.
В настоящее время может быть принято только решение для перехода на более раннюю версию: если оно было загружено в облако, напрямую получите адрес ссылки; если оно не было загружено,blob
Ссылка может сначала скопировать только адрес большого двоичного объекта, на новой вкладке первый проходfetch
Скачайте его на текущую страницу, а затем вы можете обработать его как обычный файл. Конечно, есть две проблемы с этим:
1. После копирования, немедленно закройте текущую страницу, затемblob
Память будет выпущена, и она не может быть загружена. Учитывая эту ситуацию, вы можете загружать его только непосредственно в облако при копировании или загрузке его молча в простоях; 2. В кросс-браузере вы ничего не можете сделать, Вы можете только это формат облачных ссылок.Google slides
то естьblob
превращениеurl
метод, в то время как документы Tencent загружаются напрямую, а Yuque используетbase64
Отображается в загрузке.
Конечно, некоторые люди могут сказать, что вы можете сначала преобразовать файл вbase64
, но обычно у нас есть несколько медиафайлов для копирования, на этот разbase64
Генерация займет время, а объем данных может превысить размер памяти буфера обмена. Ведь нет возможности передавать бинарные файлы между браузерами, поэтому этот отвратительный способ можно использовать только в первую очередь.
if (isBlobUrl(model.source)) {
if (medias[model.hash]) {
model.source = medias[model.hash];
} else {
let blob;
if (blob = await url2blob(model.source)) {
// 根据blobUrl重新创建当前页面的blob
const file = await blob2File(blob, model.mediaName || model.pictureName);
const blobUrl = await file2BlobUrl(file);
model.source = blobUrl;
// 缓存media数据
this.storageData.update({
medias: {
[model.hash]: blobUrl
}
});
} else {
console.error('不支持的blob_URL或者跨域');
return null;
}
}
}
использовать один напрямуюDataTransfer
объект, а затем запихивая в него данные, после тестирования это не сработает.
Конечно, если вы понимаетеclipboardItems
, вы можете почувствоватьclipboardItems
Данные могут быть вставлены в буфер обмена.
Да, вполне возможно, ноclipboardItems
Он выглядит как массив, и при использовании он также является массивом, то есть данные представляют собой массив, который поддерживает только длину 1.
6. Черная дыра на картинке
На самом деле, мне никогда не приходило в голову, что для изображений потребуется такая обработка исключений. В процессе копирования и вставки картинок вы можете не думать, что копируете «тощего человека» и в итоге получаете «толстяка», который совершенно неузнаваем;
В браузере переходимimage/png
То, что вы получаете, всегда является одним форматом изображения, потому что браузер преобразует изображение вbitmap
Вот ты, так что тыimage/png
я получил толькоbitmap
изblob
формат, это создает две проблемы:
- Вы не можете получить исходный формат изображения, вы можете получить его только
png
, о формате судить невозможно; -
bitmap
Преобразование под разные платформы отличается, что может привести к увеличению размера изображения, например,20m
фотографии, черезgetAsFileполученный метод, может превышать30m......
существуетmac
а такжеwindow
Следующий тест может дать два разных результата.
еще надо пройтиinput
Чтобы в полной мере использовать файловые возможности браузера.
Для получения подробной информации см.:
lists.what WG.org/Piper mail/me…
конец
Конечно, есть и другие проблемы, например, копирование и вставка внешних таблиц фактически требует отдельного уровня парсинга, что более хлопотно, сериализованные и десериализованные данные требуют тщательного рассмотрения, т. к. некоторые данные после форматирования форматируются. это риск трансформации...
Но в основном весь процесс копирования-вставки такой
На самом деле, полное копирование и вставка не могут быть идеальными.При различных ограничениях браузера будет много проблем, которые не могут поддерживать согласованность и могут выжить только в трещинах. Если исходное содержимое, которое необходимо скопировать и вставить, соответствуетhtml
Если она стандартизирована, с ней будет очень просто работать; если она такая же, как сцена, с которой я столкнулся, данные в основномJSON
, то потребуется много энергии, чтобы справиться с преобразованием между данными и решить некоторые граничные проблемы.